Promises数组执行不正确

时间:2017-03-27 19:56:40

标签: javascript promise jquery-deferred

我试图在所有Promise解析后执行成功函数。但是成功函数在promises得到解决之前执行。 Sufggest我的代码中出了什么问题。

var loadImg = function(imageUrls, success, failure) {
    var promises = [];
    for (var i = 0; i < imageUrls.length; i++) {
        (function(url, promise) {
            var img = new Image();
            img.onload = function() {
                promise.resolve();
            };
            img.onerror = function() {
                promise.reject();
            };
            img.src = url;
        }(imageUrls[i], promises[i] = $.Deferred()));
    }
    $.when.apply($, promises).done(success, failure);

}

1 个答案:

答案 0 :(得分:1)

如果您想在执行某些操作之前等待Promise集合完成,我建议Promise.all

让生活更轻松

首先,我们将创建一个loadImage实用程序函数,该函数接受一个网址并返回Promise的{​​{1}}

从那里开始,我们只使用新的HTMLImageElement实用程序映射您的url字符串数组 - 这会生成一个Promises数组,这正是loadImage所期望的。

Promise.all

// loadImage :: String -> Promise<HTMLImageElement> const loadImage = url => { return new Promise((resolve, reject) => { var img = new Image() img.src = url img.onload = () => resolve(img) img.onerror = (err) => reject(err) }) } const imageUrls = ['a.jpg', 'b.jpg', 'c.jpg', 'd.jpg'] Promise.all(imageUrls.map(loadImage)).then( images => console.log(images), // [<img src='a.jpg'>, <img src='b.jpg'>, ...] err => console.error(err) ) 是一个很好的第一步,因为它为我们提供了一种在我们程序中的任何一点使用promises加载图像的通用方法。每次我们需要一个图像时,我们不需要手动构建promises来处理加载。只需致电loadImage,现在就可以使用您承诺的图像了。

注意,我们现在甚至不需要显式循环。我们可以使用其他内置循环机制,如loadImage(someUrl)map,一切都按预期工作。通过编写这样的小实用函数,我们最终会编写更少的代码。

警告:如果一个无法正确加载,则不会显示任何图片。

实际使用

据推测,你想要以某种方式将图像附加到你的文档中,所以不是forEach,而是像这样的东西

console.log

使用jQuery Deferred

如果你正在寻找的话,这很容易转化为jQuery的延期 - 改变粗体

// loadImagesForElement :: (HTMLElement, [String]) -> Promise<[HTMLImageElement]>
const loadImagesForElement = (target, imageUrls) => {
  return Promise.all(imageUrls.map(loadImage)).then(
    images => images.forEach(i => target.appendChild(i)),
    err => console.error(err)
  )
}

loadImagesForElement(document.body, ['a.jpg', 'b.jpg', 'c.jpg'])
// => Promise { ... }

如果您不能依赖扩展语法,事情会变得更加丑陋 - 粗体

的变化
// loadImage :: String -> Promise<HTMLImageElement>
const loadImage = url => {
  let d = $.Deferred()
  var img = new Image()
  img.src = url
  img.onload = () => d.resolve(img)
  img.onerror = (err) => d.reject(err)
  return d.promise()
}

// loadImagesForElement :: (HTMLElement, [String]) -> Promise<[HTMLImageElement]>
const loadImagesForElement = (target, imageUrls) => {
  return $.when(...imageUrls.map(loadImage)).then(
    (...images) => images.forEach(i => target.appendChild(i)),
    err => console.error(err)
  )
}