在 JS 中使用 Promises 循环
Looping with Promises in JS
我正在尝试 运行 在 nodejs 的 for 循环内查询,并且 for 循环的每次迭代 运行 都是一个查询。查询是使用 "get()" 方法完成的,该方法 returns 是一个 Promise。在我的函数(包含这个 for 循环)中,我返回 get() 方法返回的承诺,如下所示:
for(var i=0; i < productIds.length; i++) {
return queryObject.get(productIds[i]).then(//handle result)
}
但是这个 returns 在第一次迭代之后不会继续进行其余的迭代。我该如何解决这个问题?
对于上下文,我正在使用 Parse 的云函数。
你必须像这样建立一个承诺链:
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 */})
两种可能性,并行和串行。我会展示两者:
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)
);
}
TLP给出的答案证明了Promise Chaining,在这里对你有用。但是,我将详细解释正在发生的事情并提供替代答案。
首先,让我们了解一下为什么您的代码无法执行您想要的操作:
for(var i=0; i < productIds.length; i++) {
return queryObject.get(productIds[i]).then(//handle result)
}
您希望每个 productId 的代码 运行;但是,您在第一次迭代中告诉代码 return,退出 for 循环。思考以下问题:
for(var i=0; i < productIds.length; i++) {
return productIds[i];
}
从图片中删除承诺可以更容易地看到错误。这个 for 循环等同于:
return productIds[0];
同样,您的代码等同于:
return queryObject.get(productIds[0]).then(//handle result)
假设您看到这里的错误,现在我将指出您的思考过程中的一个小错误,导致您来到这里。在你的 post 你说:
I am returning the promise returned by the get() method like so:
您指的是从 "the" 调用 get() 方法得到的单个承诺 return,但实际上您希望多次调用 get() 方法,从而产生 许多承诺。
如果所有这些都有意义,那么您的下一步是决定是否:
- 您需要 运行 在完成所有承诺后进行编码(使用检索到的数据的完整列表)。
- 您只需要 运行 每个已完成的承诺(仅使用从特定承诺中检索到的数据)的代码。
您使用 Promise Chaining 获得了第一名,如 TLP 的回答所示。您可以通过简单地从代码中删除 "return" 来实现#2,即:
for(var i=0; i < productIds.length; i++) {
queryObject.get(productIds[i]).then(//handle result)
}
我正在尝试 运行 在 nodejs 的 for 循环内查询,并且 for 循环的每次迭代 运行 都是一个查询。查询是使用 "get()" 方法完成的,该方法 returns 是一个 Promise。在我的函数(包含这个 for 循环)中,我返回 get() 方法返回的承诺,如下所示:
for(var i=0; i < productIds.length; i++) {
return queryObject.get(productIds[i]).then(//handle result)
}
但是这个 returns 在第一次迭代之后不会继续进行其余的迭代。我该如何解决这个问题?
对于上下文,我正在使用 Parse 的云函数。
你必须像这样建立一个承诺链:
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 */})
两种可能性,并行和串行。我会展示两者:
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)
);
}
TLP给出的答案证明了Promise Chaining,在这里对你有用。但是,我将详细解释正在发生的事情并提供替代答案。
首先,让我们了解一下为什么您的代码无法执行您想要的操作:
for(var i=0; i < productIds.length; i++) {
return queryObject.get(productIds[i]).then(//handle result)
}
您希望每个 productId 的代码 运行;但是,您在第一次迭代中告诉代码 return,退出 for 循环。思考以下问题:
for(var i=0; i < productIds.length; i++) {
return productIds[i];
}
从图片中删除承诺可以更容易地看到错误。这个 for 循环等同于:
return productIds[0];
同样,您的代码等同于:
return queryObject.get(productIds[0]).then(//handle result)
假设您看到这里的错误,现在我将指出您的思考过程中的一个小错误,导致您来到这里。在你的 post 你说:
I am returning the promise returned by the get() method like so:
您指的是从 "the" 调用 get() 方法得到的单个承诺 return,但实际上您希望多次调用 get() 方法,从而产生 许多承诺。
如果所有这些都有意义,那么您的下一步是决定是否:
- 您需要 运行 在完成所有承诺后进行编码(使用检索到的数据的完整列表)。
- 您只需要 运行 每个已完成的承诺(仅使用从特定承诺中检索到的数据)的代码。
您使用 Promise Chaining 获得了第一名,如 TLP 的回答所示。您可以通过简单地从代码中删除 "return" 来实现#2,即:
for(var i=0; i < productIds.length; i++) {
queryObject.get(productIds[i]).then(//handle result)
}