How to convert method created to return a promise with $q library to use an ES6 Promise. Angularjs app to Angular4+

江枫思渺然 提交于 2019-12-09 23:48:08

问题


Since the ES6 Promise does not have a deferred object confused on how to go about converting this to work with ES6 Promises. One solution that I was looking at is to add a deffered object manually to the Promise Constructor. see the No deffered section for the example code

Reason: I am converting the angularjs app to angular4 and using it to better understand how to work with ES6 Promises. I was going to add the deferred object, but thought that was too much of a workaround.

 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]
            }
        });

    }

回答1:


In some special cases resolve and reject can be exposed in order to replicate deferreds:

let pResolve;
let pReject;
const p = new Promise((resolve, reject) => {
  pResolve = resolve;
  pReject = reject;
});

Or deferred object can be formed:

const deferred = {};
deferred.promise = new Promise((resolve, reject) => {
    Object.assign(deferred, { resolve, reject });
});

Since deferreds aren't Promise built-in feature and are prone to be antipattern, it's preferable to solve this with constructor function only, when it is applicable.

In the code above displayPicture and the fact that promises cannot be formed instantly but on load event limits the ways the situation can be efficiently handled. It can be improved with sticking to promises for events (also beneficial for further conversion to async..await):

    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]);
    });

The promises should also make use of Angular digests in order to provide same control flow. Since promise internals don't rely on Angular services, there can be a single digest at the end:

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



回答2:


in ES6 it would be

let resolve1 = new Promise<string>((resolve, reject) => { 
   if (error) {
      reject();
   } else {
      resolve();
   }
});

Do the same for the number of promise you want to resolve, then if you want to run multiple promises, use :

Promise.all([resolve1, resolve2]).then(values => { 
  console.log(values); 
});

Or you can also declare your promises array and then resolve it

let resolvedPromisesArray = [Promise.resolve(val1), Promise.resolve(val2)];
let p = Promise.all(resolvedPromisesArray);

It will fail if one of the promises is rejected, and will run then if all success ;)

https://codecraft.tv/courses/angular/es6-typescript/promises/



来源:https://stackoverflow.com/questions/46510235/how-to-convert-method-created-to-return-a-promise-with-q-library-to-use-an-es6

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!