在 JS 中使用 Promise 循环

Posted

技术标签:

【中文标题】在 JS 中使用 Promise 循环【英文标题】:Looping with Promises in JS 【发布时间】:2018-09-27 16:31:22 【问题描述】:

我正在尝试在 nodejs 的 for 循环中运行查询,并且 for 循环的每次迭代都运行一个查询。查询是通过返回 Promise 的“get()”方法完成的。在我的函数(包含这个 for 循环)中,我返回 get() 方法返回的承诺,如下所示:

for(var i=0; i < productIds.length; i++) return queryObject.get(productIds[i]).then(//handle result)

但这会在第一次迭代后返回,并且不会在其余的迭代中继续。我该如何解决这个问题?

对于上下文,我使用 Parse 的 Cloud Functions。

【问题讨论】:

分享一个更大的代码sn-p。 我不在电脑自动取款机旁,但我很乐意回答您的任何问题 稍后回来分享更多代码。 为什么要使用 async-await 标签 我已经更新了这个问题,希望它能给你更多的信息 【参考方案1】:

你必须像这样建立一个承诺链:

let chain = Promise.resolve();

for (i=0; i<1000; i++) 
   chain = chain.then(()=>queryObject.get(objectId))


chain.then(()=> /* do something once all queries have returned a result */)

【讨论】:

不知道为什么有人对此投了反对票...请解释一下。【参考方案2】:

TLP 给出的答案演示了Promise Chaining,并将在这里为您工作。不过,我将进一步解释正在发生的事情并提供替代答案。

首先,让我们了解一下为什么您的代码无法执行您想要的操作:

for(var i=0; i < productIds.length; i++) 
    return queryObject.get(productIds[i]).then(//handle result)

您希望为每个 productId 运行代码;但是,您是在告诉代码在第一次迭代中退出 for 循环。考虑以下几点:

for(var i=0; i < productIds.length; i++) 
    return productIds[i];

从图片中删除承诺可以更容易地看到错误。这个 for 循环相当于:

return productIds[0];

同样,您的代码相当于:

return queryObject.get(productIds[0]).then(//handle result)

假设您在此处看到错误,现在我将指出您的思维过程中的一个小错误,导致您来到这里。在你的帖子中你说:

我正在返回 get() 方法返回的承诺,如下所示:

您指的是从“the”调用 get() 方法返回的单个 Promise,但实际上您希望多次调用 get() 方法,从而产生 许多 Promise

如果所有这些都有意义,那么您的下一步就是决定是否:

    您需要在所有承诺完成后运行代码(使用检索到的数据的完整列表)。 您只需要为每个已完成的 Promise 运行代码(仅使用从特定 Promise 检索到的数据)。

如 TLP 的回答所示,您使用 Promise Chaining 实现了 #1。您可以通过简单地从代码中删除“return”来实现#2,即:

for(var i=0; i < productIds.length; i++) 
    queryObject.get(productIds[i]).then(//handle result)

【讨论】:

我认为这应该可行。我会尝试这两种方法并更新您【参考方案3】:

两种可能性,并行和串行。我将同时显示:

async function serial(productIds) 
  for(const productId of productIds) 
      await queryObject.get(productId).then(//handle result)
  


function parallel(productIds) 
  return Promise.all(
     productIds.map( productI => queryObject.get(productId).then(//handle result)
  );

【讨论】:

我会试一试并告诉你。谢谢! 我尝试了这种方法,它按顺序获取每个产品,但我调用它的主要方法在 for 循环的第一次迭代后继续执行。我如何使 main 函数仅在 serial() 函数完成执行所有查询后才继续执行

以上是关于在 JS 中使用 Promise 循环的主要内容,如果未能解决你的问题,请参考以下文章

ES6 promise时序,本质,常见错误

在 JS 中使用 Promise 循环

JS-JS模拟实现Promise-源码解析

requset.js 封装promise的请求方法

ES6新特性:Javascript中内置的延迟对象Promise

Promis 实例