Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 加载所有图像时解析承诺_Javascript_Angularjs_Angular Promise - Fatal编程技术网

Javascript 加载所有图像时解析承诺

Javascript 加载所有图像时解析承诺,javascript,angularjs,angular-promise,Javascript,Angularjs,Angular Promise,我使用以下代码预加载图像: function preLoad() { var deferred = $q.defer(); var imageArray = []; for (var i = 0; i < $scope.abbreviations.length; i++) { imageArray[i] = new Image(); imageArray[i].src = $scope.

我使用以下代码预加载图像:

    function preLoad() {
        var deferred = $q.defer();
        var imageArray = [];
        for (var i = 0; i < $scope.abbreviations.length; i++) {
            imageArray[i] = new Image();
            imageArray[i].src = $scope.abbreviations[i].imgPath;
        }
        imageArray.forEach.onload = function () {
            deferred.resolve();
            console.log('Resolved');
        }
        imageArray.forEach.onerror = function () {
            deferred.reject();
            console.log('Rejected')
        }
        return deferred.promise;
    }
    preLoad();
这是可行的,但我想了解:

  • 每个函数中发生了什么
  • 为什么我需要
    $q.all
    来确保在解析承诺之前加载所有图像

  • 这些有点神秘。

    我不习惯使用这个库,但其想法如下:

    function getImagePromise(imgData) {
        var imgEl = new Image();
        imgEl.src = imgData.imgPath;
    
        return $q(function(resolve, reject){
            imgEl.addEventListener('load', function(){
                if ((
                       'naturalHeight' in this 
                        && this.naturalHeight + this.naturalWidth === 0
                    ) 
                    || (this.width + this.height == 0)) {
                    reject(new Error('Image not loaded:' + this.src));
                } else {
                    resolve(this);
                }
            });
    
            imgEl.addEventListener('error', function(){
                reject(new Error('Image not loaded:' + this.src));
            });
        })
    }
    
    function preLoad() {
        return $q.all($scope.abbreviations.map(getImagePromise));
    }
    
    // using
    preLoad().then(function(data){
        console.log("Loaded successfully");
        data.map(console.log, console);
    }, function(reason){
        console.error("Error loading: " + reason);
    });
    
    看看这个

    你的职能:

    function preLoad() {
    
        var promises = [];
    
        function loadImage(src) {
            return $q(function(resolve,reject) {
                var image = new Image();
                image.src = src;
                image.onload = function() {
                  console.log("loaded image: "+src);
                  resolve(image);
                };
                image.onerror = function(e) {
                  reject(e);
                };
            })
        }
    
        $scope.images.forEach(function(src) {
          promises.push(loadImage(src));
        })
    
        return $q.all(promises).then(function(results) {
            console.log('promises array all resolved');
            $scope.results = results;
            return results;
        });
    }
    
    这个想法与Henrique的答案非常相似,但onload处理程序用于解析每个承诺,onerror用于拒绝每个承诺

    回答您的问题:

    1) 承诺工厂

    $q(function(resolve,reject) { ... })  
    
    构建一个承诺。传递给
    resolve
    函数的任何内容都将在
    then
    函数中使用。例如:

    $q(function(resolve,reject) {
         if (Math.floor(Math.random() * 10) > 4) {
             resolve("success")
         }
         else {
             reject("failure")
         }
    }.then(function wasResolved(result) {
        console.log(result) // "success"
    }, function wasRejected(error) {
        console.log(error) // "failure"
    })
    

    2) $q.all被传递一个承诺数组,
    然后
    接受一个函数,该函数被传递一个具有所有原始承诺分辨率的数组。

    你从哪里得到这个
    imageArray.forEach.onload
    的?@HenriqueBarcelos你的意思是它应该是
    imageArray.onload
    吗?我想知道你为什么要谈论“第一个承诺“…您的第一个代码片段中只有一个承诺。我认为您的第二个代码不起作用。是的,它确实会记录最后一条消息,但记录得太早了。此代码中没有任何地方您正在等待
    加载
    错误
    事件,我非常确信,
    $q.when
    在传递
    图像时不会自动执行此操作,这两种方法都不起作用。您是否故意遗漏了添加
    onerror
    处理程序?您的意思是
    Image
    元素的
    onerror
    处理程序?只有当响应状态与
    200
    不同。对于可以返回
    200
    状态,但响应内容(mime)不是图像的情况,我在文章中使用的方法是防弹的。这是相关的。是的,但是当返回no 200状态时会触发afaik(以及我如何理解)no
    load
    事件-在某些情况下,只会触发
    error
    。您是对的,因此稳健的解决方案必须包括这两种方法。我会修改答案,我看不出有什么区别。“但是onload处理程序用于解析每个承诺,onerror用于拒绝每个承诺”是什么意思?顺便说一句,你应该在你的答案中发布你的代码,尤其是
    loadImage
    函数,而不是在某个插件上。很好,你说得对&它是经过编辑的。为了回答您的问题,我相信onerror处理程序可以决定是否拒绝,而不是在onload处理程序中决定解决/拒绝。onload处理程序只能解析。取决于用例,但是如果您需要更细粒度的拒绝标准,则其他解决方案可能更好。另外,我想更深入地向奥帕解释承诺,对吧。请注意,Henrique也必须解决这个问题,有关详细信息,请参见其答案上的评论:-)@ShaharZ感谢您的努力。乍一看,你的片段比亨里克的更清晰。我也要试一试+1.@ShaharZ在链接函数
    console.log(newVal,oldVal)中返回
    未定义,未定义
    $q(function(resolve,reject) {
         if (Math.floor(Math.random() * 10) > 4) {
             resolve("success")
         }
         else {
             reject("failure")
         }
    }.then(function wasResolved(result) {
        console.log(result) // "success"
    }, function wasRejected(error) {
        console.log(error) // "failure"
    })