【问题标题】:Angular JS (1.2.26) promises in a forEach loopAngular JS (1.2.26) 在 forEach 循环中承诺
【发布时间】:2023-03-20 21:43:02
【问题描述】:

我有一个 angular.forEach 循环,它遍历图像配置对象,以便根据配置中的 URL 创建 javascript Image() 对象。

希望在所有图像都正确加载之前返回结果图像。如何通过使用 Angular 承诺来实现这一目标?

考虑以下(简化的)代码 sn-p:

function getImages(imageConfigurations) {
    var images = [];

    angular.forEach(imageConfigurations, function (config) {
        var imageObject = loadImageFromUrl(config.url);

        var imageData = {
            name: config.name,
            order: config.order,
            image: imageObject
        };

        images.push(imageData);

    });

    //Do not return this untill all of the image objects from forEach loop 
    //have fired their 'onload' event
    return images;

}

function loadImageFromUrl(url) {
    var imageObj = new Image();

    imageObj.onload = function () {
        //Resolve promise?
    };

    imageObj.src = url;
} 

【问题讨论】:

  • 你可能想要$q.all()。让您的loadImageFromUrl 调用从$q.defer() 返回一个承诺并在onload 上解决它。

标签: javascript angularjs image onload angular-promise


【解决方案1】:

以下要求您注入$q 服务...

您可以做的第一件事是将图像加载包装在一个承诺中,例如

function loadImageFromUrl(url) {
    return $q(function(resolve) { // ignoring error conditions for now
        var imageObj = new Image();

        imageObj.onload = function () {
            resolve(imageObj);
        };

        imageObj.src = url;
    });        
}

然后,您可以使用 $q.all 等待所有的 Promise 解决

function getImages(imageConfigurations) {
    // map imageConfigurations to an array of promises
    var promises = imageConfigurations.map(function(config) {
        return loadImageFromUrl(config.url).then(function(imageObj) {
            // chain the loadImageFromUrl promise to create the
            // imageData object and return it to resolve the promise
            return {
                name: config.name,
                order: config.order,
                image: imageObj
            };
        });
    });

    return $q.all(promises);
}

当该承诺解决时,您将拥有一个 imageData 对象数组

getImages(configs).then(function(imageDataArray) {
    // tada!
});

这是 Angular 1.2.x 所需的 loadImageFromUrl 版本。见https://code.angularjs.org/1.2.26/docs/api/ng/service/$q

function loadImageFromUrl(url) {
    var deferred = $q.defer(),
        imageObj = new Image();

    imageObj.onload = function () {
        deferred.resolve(imageObj);
    };
    imageObj.src = url;

    return deferred.promise;
}

【讨论】:

  • 甚至不知道你可以通过 $q(...) 来创建一个承诺,谢谢!
  • @MathewBerg 这是最近添加的。我发现它看起来比创建延迟对象更好,尽管在功能上我认为它们是相同的
  • @Phil:对于这个项目,我们仅限于使用旧版本的 Angular(我相信是 1.2.6)。 $q(...) 还能用吗?
  • @LucMorrissette 你真的应该早点提到这一点。不,您需要使用延迟对象。我已经更新了答案
【解决方案2】:

注意 getImages 现在是异步的 -

  function getImages(imageConfigurations) {
     var deferred = $q.defer();
     var images = [];
     var imagePromises = imageConfigurations.map(function (config) {
         var imagePromise = loadImageFromUrl(config.url);
         return imagePromise;
     });

     return $q.all(imagePromises).then(function(images){
          return images.map(function(imageObject){
             // create image object 
           })
        });
 }  

从 url 加载图像现在也是异步的 -

   function loadImageFromUrl(url) {
         var defer = $q.defer();
         var imageObj = new Image();

         imageObj.onload = function () {
            defer.resolve("image has been loaded - yay");
         };

         imageObj.src = url;

         return defer.promise;
     }

$q 文档请到这里 - https://docs.angularjs.org/api/ng/service/$q

祝你好运

【讨论】:

  • 我在这里看到的一个大问题是,创建图像数据对象(nameorder)所需的 config 项目在您需要时将不可用。你可以改变它,但是这个答案看起来更像上面的那个
  • 另一个问题是loadImageFromUrl 用字符串解析。 getImages 不返回已解析图像承诺的数组,它返回已解析为“耶”的承诺数组。
猜你喜欢
  • 1970-01-01
  • 2015-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-13
  • 1970-01-01
  • 2014-11-25
  • 1970-01-01
相关资源
最近更新 更多