一个nodeJS脚本,里面有一个函数:
async myFunc1(a, b, c) {
//.......
}
它返回一些值,但不是Promise
。我曾经这样运行它:
let a1 = await myFunc1(1, "fds", 99);
现在我需要同时运行几十个函数,它们的数量和参数的输入来自用户。
let lines = readDataFromUserProvidedFile();
for (let i = 0; i < lines; i++) {
//
//how to run all the myFunc1(...) in parallel??
//and then print out a result of each?
//(?)
myFunc1(lines[i], i, i*2);
}
这样的话我怎么并行运行呢?而且当后面的一个返回结果的时候,我想马上打印出来。
对于这个函数来说,返回一个值大约需要10分钟,它不进行计算,而是等待来自远程Web服务的结果。
2条答案
按热度按时间jyztefdp1#
更新日期:2023年3月16日
for...await
从每次迭代的序列求值。它将按顺序遍历promises
数组。如果数组中的第一个承诺花费10分钟,第二个承诺花费5分钟。它将不记录5分钟内完成的承诺。“边走边记录”或在承诺完成时记录。有几种方法可以做到这一点。这将取决于您希望在代码的正常流程中有多少控制权。
您可以使用
.forEach
+.then
:您可以删除
.map
并执行以下操作:通过这种方式,它将在每个问题得到解决时打印其结果--一个接一个。
如果您希望更好地控制要解析的承诺,则需要手动管理每个承诺的状态。
Promise.all
和Promise.allSettled
将等到所有承诺完成后才将控制权移交给您/您的代码。这不是您想要的。Promise
对象represents an asynchronous操作的最终完成(或失败)及其结果值。您需要使用异步迭代对象来执行、控制和返回每个交互的值。功能示例:
由于
Promise
对象没有任何“状态”信息,我们需要手动使用.map
来告诉代码在.then
之后完成了哪个承诺。Promice.race
将返回第一个已解析的承诺,在解析之后,我们使用.splice
将其从数组中删除。所有这一切都是因为没有状态信息“as-you-go”(例如,当它正在被解决时)。
JS生态系统中的库可以为您抽象这些内容,并使用队列创建更好的解决方案。
例如:
原始答案
你可以创建一个并行执行的承诺集合,然后在集合上迭代等待:
伪代码:
j13ufse22#
因此,承诺有两个部分。执行它们和等待它们。等待它们意味着当你得到一个结果时,你附加了一个回调来做某事。执行它们意味着只是“把它们踢出去”
问题是你使用的是
await
,启动异步进程和等待异步进程的结果是有区别的,具体来说,你可以启动一个异步进程,并在稍后将对它的引用保留给await
,而不用立即对它进行await
-ing。tl;dr您仍然可以使用
async/await
,只需使用.map
立即启动所有承诺: