Javascript 如何将创建用于返回带有$q库的承诺的方法转换为使用ES6承诺。Angularjs应用程序到Angular4+;

Javascript 如何将创建用于返回带有$q库的承诺的方法转换为使用ES6承诺。Angularjs应用程序到Angular4+;,javascript,angularjs,angular,es6-promise,Javascript,Angularjs,Angular,Es6 Promise,由于ES6承诺没有延迟对象,因此在如何将其转换为与ES6承诺一起使用时会产生混淆。我正在研究的一个解决方案是手动向Promise构造函数添加一个不同的对象 原因:我正在将angularjs应用程序转换为angular4,并使用它更好地了解如何使用ES6承诺。我本来打算添加延迟对象,但认为这是一个太多的变通方法 function generateImages() { console.log('generateImagesCalled') // set up pr

由于ES6承诺没有延迟对象,因此在如何将其转换为与ES6承诺一起使用时会产生混淆。我正在研究的一个解决方案是手动向Promise构造函数添加一个不同的对象

原因:我正在将angularjs应用程序转换为angular4,并使用它更好地了解如何使用ES6承诺。我本来打算添加延迟对象,但认为这是一个太多的变通方法

 function generateImages() {
        console.log('generateImagesCalled')

        // set up promises
        var fullDeferred = $q.defer();
        var thumbDeferred = $q.defer();

        var resolveFullBlob = blob => fullDeferred.resolve(blob);
        var resolveThumbBlob = blob => thumbDeferred.resolve(blob);

        var displayPicture = (url) => {
            var image = new Image();
            image.src = url;

            // Generate thumb
            var maxThumbDimension = THUMB_IMAGE_SPECS.maxDimension;
            var thumbCanvas = _getScaledCanvas(image, maxThumbDimension);
            thumbCanvas.toBlob(resolveThumbBlob, 'image/jpeg', THUMB_IMAGE_SPECS.quality);

            // Generate full
            var maxFullDimension = FULL_IMAGE_SPECS.maxDimension;
            var fullCanvas = _getScaledCanvas(image, maxFullDimension);
            fullCanvas.toBlob(resolveFullBlob, 'image/jpeg', FULL_IMAGE_SPECS.quality);
        }

        var reader = new FileReader();
        reader.onload = (e) => {
            displayPicture(e.target.result);
        }
        reader.readAsDataURL(vm.currentFile);


        return $q.all([fullDeferred.promise, thumbDeferred.promise]).then(results => {
            console.log(results);
            return {
                full: results[0],
                thumb: results[1]
            }
        });

    }
在ES6中,它将是

let resolve1 = new Promise<string>((resolve, reject) => { 
   if (error) {
      reject();
   } else {
      resolve();
   }
});
或者您也可以声明承诺数组,然后解析它

let resolvedPromisesArray = [Promise.resolve(val1), Promise.resolve(val2)];
let p = Promise.all(resolvedPromisesArray);
如果其中一个承诺被拒绝,它将失败;如果所有承诺都成功,它将运行;)


在某些特殊情况下,可以公开
解决
拒绝
以复制延迟:

let pResolve;
let pReject;
const p = new Promise((resolve, reject) => {
  pResolve = resolve;
  pReject = reject;
});
或者可以形成延迟对象:

const deferred = {};
deferred.promise = new Promise((resolve, reject) => {
    Object.assign(deferred, { resolve, reject });
});
由于延迟不是内置的功能,并且容易成为反模式,因此最好仅使用构造函数(如果适用)来解决此问题

在上面的代码中,
displayPicture
和承诺不能立即形成,但在
load
事件上限制了有效处理情况的方式。它可以通过遵守事件承诺来改进(也有利于进一步转换为
async..wait
):

为了提供相同的控制流,promises还应使用角度消化。由于promise内部不依赖于角度服务,因此最后可以有一个摘要:

    return blobPromises.then(
      () => $rootScope.$apply(),
      err => {
        $rootScope.$apply();
        throw err;
      }
    );
    // or
    return $q.resolve(blobPromises);

为什么您要将其转换为ES6 promise?它与Angular digest集成时会有额外的问题,这是$q为您做的事情。我正在将应用程序转换为angular4,并使用它更好地了解如何使用ES6。我本来打算添加延迟对象,但我认为这是一个太多的解决办法。我建议在问题中说明这一点,这将使它对有类似问题的读者更有用。为什么你甚至在不应该使用延迟的情况下提到延迟呢?@Bergi为了完整性起见,因此,读者可以估计选项,并就此做出自己的决定。大多数时候不应该使用延迟并不意味着它们根本不应该被使用。我已经为他们准备了相当多的好用例。@estus谢谢-让它工作了-即使在你的帮助下-它仍然是令人费解的。使用延迟模式已经很长时间了。感觉就像我在学习承诺一样。一个问题:你为什么提到angular4的消化周期。不要认为angular4中有摘要循环。是的,没有摘要(从技术上讲,区域是相似的,会导致自动变化检测)。这个问题不清楚您是在逐步重构A1应用程序,以便稍后将其转换为A4,还是在A4中重写它。上面的示例是经得起未来考验的A1代码,它可以按原样在A4中使用,但不需要$rootScope或$q。
    const readerPromise = new Promise(resolve => reader.onload = resolve);
    reader.readAsDataURL(vm.currentFile);

    const blobPromises = readerPromise.then(e => {
      const url = e.target.result;

      const fullBlobPromise = new Promise(resolve => {
        ...
        fullCanvas.toBlob(resolve, ...);
      });

      const thumbBlobPromise = ...;

      return Promise.all([fullBlobPromise, thumbBlobPromise]);
    });
    return blobPromises.then(
      () => $rootScope.$apply(),
      err => {
        $rootScope.$apply();
        throw err;
      }
    );
    // or
    return $q.resolve(blobPromises);