【问题标题】:await promise result before next loop iteration在下一次循环迭代之前等待承诺结果
【发布时间】:2015-12-22 12:02:17
【问题描述】:

我在每次循环迭代中运行一个函数,但是我需要确保在下一次迭代运行之前收到回调(成功)。当我运行下面的代码时,它会运行循环,然后控制台会显示所有回调结果。

var getExerciseImages = function(exerciseImages) {

    var deferred = $q.defer();
    var imageColumns = [];
    var imageObject = {};

    for (var i = 0; i < exerciseImages.length; i++) {

        var url = 'http://files.s3.amazonaws.com/medium/' + exerciseImages[i] + '.jpg'

        convertImgToBase64URL(url).then(function(result) {

            imageObject = {
                image: result,
                fit: [200, 200]
            };

            imageColumns.push(imageObject);
        });

    };

    deferred.resolve(imageColumns);

    return deferred.promise;
};

调用外部函数:

function convertImgToBase64URL(url, callback, outputFormat) {
    var deferred = $q.defer();

    var img = new Image();
    img.crossOrigin = 'Anonymous';
    img.onload = function() {
        var canvas = document.createElement('CANVAS'),
            ctx = canvas.getContext('2d'),
            dataURL;
        canvas.height = this.height;
        canvas.width = this.width;
        ctx.drawImage(this, 0, 0);
        dataURL = canvas.toDataURL(outputFormat);
        // callback(dataURL);
        deferred.resolve(dataURL);
        canvas = null;
    };
    img.src = url;

    return deferred.promise;
};

如果有更好的方法,我愿意接受有关其他方法的建议?

【问题讨论】:

  • 您不能等待 Javascript 中的异步结果。您必须在回调函数中执行下一步。
  • 好的,你有什么好的资源可以让我按顺序执行三个函数吗?
  • 看看stackoverflow.com/questions/15504921/…。它适用于 jQuery,但基本思想与泛型 Promise 相同。

标签: javascript loops callback promise


【解决方案1】:

异步操作不能停止脚本的执行,但是我们可以重构您的代码以避免deferred anti-pattern,而是使用$q#resolve$q#all,以便专门使用Promises 处理所有数据和逻辑。

var getExerciseImages = function (exerciseImages) {

    // Create a resolved Promise whose value is `exerciseImages` array
    // Use 'when' in place of 'resolve' if using Angular
    return $q.resolve(exerciseImages).then(function (arr) {

        // Map each element to a Promise created by `convertImgToBase64URL`
        // and wait for them all to resolve by wrapping the resulting
        // array of Promises in `$q#all` 
        return $q.all(arr.map(function (url) {

            var url = 'http://files.s3.amazonaws.com/medium/' + url + '.jpg'
            return convertImgToBase64URL(url).then(function (result) {
                return {
                    image: result,
                    fit: [200, 200]
                };
            });
        }));
    });
};

这个方法的结果是一个 Promise,它的值是一个对象数组,每个对象有两个属性 imagefit

var images = []; // An array of URLs 
getExerciseImages(images).then(function (data) {
    console.log(data); // => [{image, fit}, ...]
});

提醒一下,在 ES7 中有 async functions 可以是 awaited。

【讨论】:

  • 嗨,非常感谢您的回答 - 我收到了 $q.resolve is not a function 错误。
  • @Taylorsuk 试试$q.when if you are using Angular
  • 不确定 - 这是使用 Ionic 框架。 q.when 对错误进行排序。效果很好 - 谢谢。
猜你喜欢
  • 1970-01-01
  • 2020-11-18
  • 1970-01-01
  • 2015-05-12
  • 2020-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-13
相关资源
最近更新 更多