等待数组中的嵌套承诺

Waiting for nested promises inside an array

我正在创建一个函数来在需要时延迟加载图像(使用分页将大数据集分成较小的块)。

问题是 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);
    });
}

你说得对。 promise 解析器不会在另一个对象中搜索 promise。你需要 return 对你想要完成的整个事情做出承诺,尽管你可以分段完成。在这里,我添加了一个单独的函数,该函数 return 是对 items[i] 的承诺,通过链接 getItemImage 承诺结果来改变 .imagedata。这个承诺反过来应该对所有人都可用,所以 Promise.all 在所有图像都发生变化时触发。

除非你在某个地方实现一个需要回调参数的遗留接口,否则最好在最后使用 return Promise.all(promises) 这样调用者可以决定是否通过它自己的回调直接回调或将更多操作链接到 promise 解析以及如何处理错误。

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);
        });
}