以孤立的方式处理承诺列表的最佳方式是什么?

What's the best way to handle a list of promises in an isolated manner?

我一直在思考用 Javascript 处理一批繁重操作的最佳方法是什么,我想出了以下方法:

const results: Promise<void>[] = [];

// Start all pieces of work concurrently
for (const record of await getData()) {
  results.push(doSomeHeavyWork(records));
}

// Collect the results
for (const result of results) {
  // Isolate the failures so one doesn't break another.
  try {
    await result;
  } catch (error) {
    console.log(JSON.stringify(error));
  }
}

我的理解是,上面的代码片段需要的时间与最长的操作一样长,这与 AFAIK 一样好。但是,有没有更好或更惯用的方法来解决这个问题?

我并不是真的在看这里的节点。这可能是节点、Deno 或浏览器代码。

在您的代码中,仅将 promises 推入数组不会启动并发工作,但您将以并发方式解决它们的方式。在这个for循环中,results数组的每一项都会一个接一个的同步执行,没有任何并发​​执行,性能会很低。

javascript 提供了一种实现这种“并发”执行的方法,使用 Promise 本机的 all 静态方法 class:

const results: Promise<void>[] = [];

// Start all pieces of work concurrently
for (const record of await getData()) {
  results.push(doSomeHeavyWork(records));
}

// Without handling errors will be just like this
await Promise.all(results);

在上面的例子中,所有的 promise 都会被解决,但是如果一个失败,所有的 promise 也会失败(如果这不是你想要的,请考虑查看更多关于 allSettled 的内容)。要处理每个 promise 错误,您只需将一个 catch 块附加到数组中的每个 promise:

const results: Promise<void>[] = [];

// Start all pieces of work concurrently
for (const record of await getData()) {
  results.push(doSomeHeavyWork(records));
}

// Handling errors will be just like this
await Promise.all(results.map(r => r.catch(error => console.log(JSON.stringify(error)))));

注意:并发是低引号,因为nodeJS是单线程语言,所以这种并发不会发生在不同的线程。