【问题标题】:Node JS Async Promise.All issuesNode JS Async Promise.All 问题
【发布时间】:2016-04-30 17:10:28
【问题描述】:

我正在尝试对从数据库获取的列表中的一堆项目执行异步例程,但我无法理解 promise.all 的工作原理及其作用。

这是我现在使用的代码:

/**
 * Queues up price updates
 */
function updatePrices() {

     console.log("~~~ Now updating all listing prices from Amazon API ~~~");

    //Grabs the listings from the database, this part works fine    
    fetchListings().then(function(listings) {

        //Creates an array of promises from my listing helper class 
        Promise.all(listings.map(function(listing){

            //The promise that resolves to a response from the routine
            return(listing_helper.listingPriceUpdateRoutine(listing.asin));
        })).then(function(results){

            //We want to log the result of all the routine responses
            results.map(function(result){
                console.log(result);
            });

            //Let us know everything finished
            console.log("~~~ Listings updated ~~~");
        }).catch(function(err){
            console.log("Catch: ", err);
        });
    });
}

现在,我在日志中得到的唯一信息是

~~~ 现在从 Amazon API 更新所有列表价格~~~

我尝试在被调用的例程中添加一个日志记录片段,这些例程都成功运行并记录了它们应该记录的内容,但是 promise.all.then 没有执行。

我已经尝试过:

Promise.all(bleh).then(console.log("我们做到了"));

这行得通,但是当我在 Then 中放置一个函数时,没有任何运行。

请帮忙!

【问题讨论】:

  • tl;博士; - 你在链中的承诺之前错过了回报。
  • 好的,快速查看一下代码 - 您缺少两个 returns。一个在你的Promise.all 之前和一个在fetchListings() 之前,承诺按返回值工作——如果你不从then 处理程序返回,它不会等待任何东西。
  • 另外,您调用的所有函数都是返回承诺的函数吗?您需要进一步隔离您的问题。
  • 您是否控制台记录了所有 isting_helper.listingPriceUpdateRoutine(listing.asin)?真的全部完成了吗(count === listens.length?)
  • @BenjaminGruenbaum 你的建议似乎并没有改变我的结果。 updatePrices 不需要返回任何东西,它只需要记录信息。我尝试将 return 放在 Promise.all 前面和 fetchListings().then 前面,但它什么也没改变。

标签: javascript node.js asynchronous


【解决方案1】:

Promise.all() 本身非常简单。你向它传递一系列承诺。它返回一个新的 Promise,当你的数组中的所有 Promise 都解决时,它会解决,或者当数组中的任何单个 Promise 被拒绝时,它会被拒绝。

var pAll = Promise.all([p1, p2, p3]);

pAll.then(function(r) {
    // all promises resolved
    // r is an array of results
}, function(err) {
    // one or more promises rejected
    // err is the reason for the first promise that rejected
});

Promise.all() 可能无法在您的代码中运行的一些原因:

  1. 您没有向它传递一系列承诺。
  2. 您传递的数组中的某些承诺永远不会解决或拒绝,因此 Promise.all() 永远不会解决/拒绝其主承诺
  3. 您没有正确地将回调传递给您应该在的 .then() 处理程序
  4. 您没有从内部函数正确返回 Promise,因此它们可以正确传播或链接

你的例子:

Promise.all(bleh).then(console.log("We did it"));

错了。您必须像这样将函数引用传递给.then()

Promise.all(bleh).then(function() {
    console.log("We did it")
});

在您的情况下,console.log() 将立即执行,而不是等待承诺得到解决。


在您的详细代码中,您是否 100% 确定:

listing_helper.listingPriceUpdateRoutine(listing.asin)

返回一个承诺?而且,该承诺会被正确解决或拒绝吗?


读者须知 - 如果您阅读了所有 cmets,您会发现 OP 的实际问题不在于 Promise.all(),但由于向目标发送请求太快而受到速率限制主持人。由于这应该会传播一个应该很容易看到的请求错误,因此 OP 显然也存在错误处理或传播问题,这可能在此处未公开的代码中。

【讨论】:

  • 我已经检查了几次其中的所有方法,我将再次检查它们以确定。我会粘贴整个东西,但它很大,其中一些可能不太酷。
  • @user2172205 - 您需要在调试器中跟踪它或添加更多console.log() 语句以查看它停止执行的位置。除了建议您使用调试工具解决问题外,我们对此无能为力。例如,将console.log() 放在fetchListings().then() 处理程序的第一行。将一个放在第一个 .map() 回调中。验证来自listing_helper.listingPriceUpdateRoutine(listing.asin)等的每个返回结果...
  • 好的,我发现了这个问题,我想,我受到 API 的限制,因为我曾经将请求放在漏桶中。有什么办法可以在“地图”执行中的每个项目之间进行延迟?
  • @user2172205 - 正确的错误处理应该向您表明您从请求中得到了某种错误。将您的问题更改为关于速率限制请求的全新问题在这里并不是很酷。你问这个关于Promise.all() 的问题,我们已经回答了很多。如果您想询问有关限制请求的速率或使用漏桶的新问题,您应该对该主题进行大量研究,包括所有先前有关堆栈溢出的相关问题/答案,然后如果您仍然需要发布新问题帮助。
  • 抱歉,感谢您的回答。出于某种原因,错误没有在我的堆栈中弹出,所以我必须解决这个问题。
猜你喜欢
  • 2020-12-19
  • 1970-01-01
  • 1970-01-01
  • 2021-06-24
  • 2020-11-12
  • 2011-08-29
  • 1970-01-01
  • 2014-02-13
  • 1970-01-01
相关资源
最近更新 更多