【问题标题】:Make my asyncForEach() Parallel Instead of Sequential使我的 asyncForEach() 并行而不是顺序
【发布时间】:2020-07-30 12:21:10
【问题描述】:

所以我希望循环内的代码同时运行,但循环后的代码仅在循环完成处理时运行:

代码

async function asyncForEach(array, callback) {
  for (let index = 0; index < array.length; index++) {
    await callback(array[index], index, array);
  }
}

const waitFor = (ms, num) => new Promise(r => setTimeout(() => {
  console.log(num)
  r()
}, ms));

const doStuff = async() => {

  await asyncForEach([1, 2, 3], async(num) => {
    await waitFor(1000, num);
  })

  console.log('Done');
}

doStuff()

输出

/* Output
1   - takes 1 sec
2   - takes 1 sec
3   - takes 1 sec
Done
    - total 3 sec
*/

我想要什么

/* What I want
    _
1    |
2    | - takes 1 sec
3   _|
Done
    - total 1 sec
*/

【问题讨论】:

  • 请不要通过输入无关字符来绕过网站规则,以便您的标题是一个与另一个不同的字符。相反,请阅读 How to Ask 并想出一个更好的标题,更独特地描述您的特定问题,或者更好的是,阅读其他问题,看看您的问题之前是否有人问过。
  • Javascript 是 single-threaded language。这意味着它有一个调用栈和一个内存堆。你无法在 JS 中实现你想要的。每个函数都在事件循环中被一一调用。
  • @HereticMonkey 我让标题更具描述性,作为他们将来使用的示例。

标签: javascript node.js asynchronous async-await


【解决方案1】:

使用Array.prototype.map()Promise.all()

const asyncForEach = async (array, callback) => {
  await Promise.all(
    array.map(callback)
  );
};

const waitFor = (ms, num) => new Promise(resolve => {
  setTimeout(() => {
    console.log(num);
    resolve();
  }, ms);
});

const doStuff = async () => {
  await asyncForEach([1, 2, 3], async num => {
    await waitFor(1000, num);
  });

  console.log('Done');
};

doStuff();

【讨论】:

  • 注意:您的callback 函数将使用map 始终传递给回调的附加参数进行调用。确保被调用的函数不会因此而行为异常(参见parseIntmap 的行为)
  • 附注asyncForEach 这里不需要严格地标记为async,因为它不会用await 调用任何东西,并且总是会返回Promise
  • @Alnitak 请注意,回调是使用问题中的相同参数调用的。 async 不需要在那里,但鉴于这是 asyncForEach 而不是 asyncMap,我无论如何都应该将其更改为不在承诺解析中返回数组。
  • 哎呀,是的,我自己没有发现 OP 正在复制 forEach 回调参数结构,尽管该评论更适合其他读者而不是您。
猜你喜欢
  • 1970-01-01
  • 2016-11-17
  • 2017-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多