【问题标题】:Calling then before or after Promise.all然后在 Promise.all 之前或之后调用
【发布时间】:2016-04-13 09:29:13
【问题描述】:

目前我有以下代码:

var detailPromises = links.map(function (link) { return requestP(link) });

var oldPollNames = [];
// add a database call to the promises as it also can resolved during detail fetching
detailPromises.push(db.polls.findAsync({}, {title: 1}));
return Promise.all(detailPromises)
    .then(function (data) {
        oldPollNames = data.pop().map(function (item) { return item.title; });
        return data;
    })
    .then(function (htmls) {
        var newPolls = [];
        htmls.forEach(function (i, html) {
            // some processing of html using oldPollNames (newPools.push...)
        });
        return newPolls;
    })
    .then(/* insert into db */);

我在做的是:等待db+等待html请求,然后处理booth。

我想知道执行以下操作是否更有意义/更高效:

var detailPromises = links.map(function (link) { return requestP(link) });

return db.polls.findAsync({}, {title: 1}).then(function(polls) {
    var oldPollNames = polls.map(function (item) { return item.title; });
    var newPolls = [];

    detailPromises = detailPromises.map(function (p) {
        return p.then(function (html) {
            // some processing of html using oldPollNames (newPools.push...)
        })
    });

    return Promise.all(detailPromises)
        .done(function () {
            // insert newPolls into db
        });
});

imo 的第二种方法的优点是每个请求在完成时都(已经)得到处理,并且可以在所有/其他承诺都实现之前进行处理。

【问题讨论】:

  • 你使用的是什么承诺库? .done 是什么?
  • 你真的应该使用map 而不是forEachnewPolls 数组。
  • @Bergi 你是对的,否则 Promise.all 不会等待所有处理(newPools.push ...)完成。谢谢
  • @Bergi done 用于promisejs.org 但我实际上不知道他们为什么使用它lol
  • 啊,我明白了。 They say:“请注意,promise.done(在本节示例中用作教具)尚未标准化。”。你不应该使用它,总是去then

标签: javascript promise


【解决方案1】:

我想知道它是否更有意义/更高效

是的,单独并尽可能快地处理每个 html 请求会更高效,而不是等待所有请求然后在一个巨大的循环中一起处理它们。它们不仅会更早处理,还可以避免可能长时间运行的繁重处理循环。

但是,该方法也有其缺点:实施起来更加复杂。如果任何detailPromises 在数据库查询完成之前拒绝,或者如果其中任何一个拒绝并且数据库查询也被拒绝,您给出的代码很容易报告Unhandled Rejections。为了防止这种情况发生,无论如何你都需要在所有的 Promise 上使用 Promise.all

var detailPromises = links.map(requestP);

var resultPromise = db.polls.findAsync({}, {title: 1}).then(function(polls) {
    var oldPollNames = polls.map(function(item) { return item.title; });
    var newPollPromises = detailPromises.map(function(p, i) {
        return p.then(function(html) {
            // some processing of html
        });
    });

    return Promise.all(newPollPromies) // not the detailPromises!
    .then(function(newPolls) {
        // insert newPolls into db
    });
});
return Promise.all([resultPromise].concat(detailPromises)).then(function(r) {
    return r[0];
});

【讨论】:

  • Boarh我真的不得不认真考虑,但它完全有道理。
  • 有什么方法可以让它变得更好或者把东西放入一个函数中?我无法想象一个。
  • @velop:让哪个部分更好?
  • 我认为在 Bluebird 中您也可以使用 return Promise.all(detailPromises).return(resultPromise) 而不必担心未处理的拒绝
  • 如果我做这样的事情,你认为它是否过度工程:jsbin.com/kibozusipu/edit?js,output
【解决方案2】:

除了 Bergi 的回答之外,我想我还找到了另一个同样的解决方案:

var detailPromises = links.map(requestP);
var pollNamePromise = db.polls.findAsync({}, {title: 1}).then(function(polls) {
        return polls.map(function (item) { return item.title; });
    });

var newPromises = detailPromises.map(function(p) {
        return Promise.join(p, pollNamePromise, function(html, oldPollNames) {
            // some processing of html using oldPollNames (newPools.push...)
        });
    });

Promise.all(newPromises).then(function(newPolls) {
    // insert newPolls into db
});

编辑从 Promise.all 更改为 Promise.join,在 Bluebird 中可用

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-23
    • 1970-01-01
    • 2023-04-08
    • 2012-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-14
    相关资源
    最近更新 更多