等待数组内的嵌套promise

时间:2017-03-03 11:28:30

标签: arrays image promise paging es6-promise

我正在创建一个延迟加载图像的函数,当需要它们时(使用分页将大数据集划分为更小的块)。

问题是承诺嵌套在items[i].imagedata

返回的items数组仍然包含Promise对象而不是加载的图像。这可能是因为我使用了items.map(),它创建了数组的副本。

function getItemImages(items, paging, cb) {
    var Promise = promise.Promise;
    console.log("START",items,paging);
    for (var i=paging.pageOffset; i<Math.min(paging.pageOffset+paging.pageLimit,items.length); i++) {
        if (!items[i].hasOwnProperty("imagedata")) {
            console.log("LOADING "+i+":",items[i]);
            items[i].imagedata = mongodbService.getItemImage(items[i]._id);
        }
    }
    Promise.all(items.map((item) => {
        return Promise.all([item.imagedata]);
    })).then((images) => {
        console.log("RESULT",paging, items);
        cb(paging, items);
    });
}

1 个答案:

答案 0 :(得分:1)

你是对的。 promise解析器不会在另一个对象中搜索promise。你需要为你想要完成的整个事情返回一个承诺,尽管你可以分成几部分。在这里,我添加了一个单独的函数,该函数返回带有.imagedata的items [i]的promise,它通过链接getItemImage promise结果进行变异。反过来,这个承诺应该可以与所有人一起使用,这样Promise.all会在所有图像发生变异时触发。

除非您在某个需要回调参数的地方完成遗留接口,否则最好在最后返回Promise.all(promises),以便调用者可以决定是否通过自己的回调直接回调或者将更多操作链接到承诺解决方案以及如何处理错误。

function getItemImages(items, paging, cb) {
    var Promise = promise.Promise;
    console.log("START",items,paging);
    // Return a promise for items[i] with .imagedata
    function promiseImage(i) {
        return mongodbService.getItemImage(items[i]._id).
            then(function(image) {
                items[i].imagedata = image;
                return items[i];
            });
    }
    var promises = [];
    for (var i=paging.pageOffset; i<Math.min(paging.pageOffset+paging.pageLimit,items.length); i++) {
        if (!items[i].hasOwnProperty("imagedata")) {
            console.log("LOADING "+i+":",items[i]);
            // Add a new promise to promises
            promises.push(promiseImage(i));
        }
    }
    // promises is an array of promises, so "all" will work.
    // Your code uses mutation, so the result isn't needed here.
    // Previously, items was being sent to cb.
    // cb might also consume the actual list of mutated items
    // below.
    Promise.all(promises).
        then(() => {
            console.log("RESULT",paging, items);
            cb(paging, items);
        });
}