JavaScript 异步循环 - async/await 的使

2019-01-12  本文已影响0人  millerLMF

如何以顺序或并行方式运行异步循环?

在对循环进行异步处理之前,我想提醒您如何编写经典的同步循环。

同步循环

很久以前我也是这样写For循环:

for (var i=0; i < array.length; i++) {
  var item = array[i];
  // do something with item
} 

这样写很好,速度很快,但是有很多可读性和维护问题。我们可以用它更好的版本:

array.forEach((item) => {
  // do something with item
});

JS语言在开发中运行很快,我们还有更多的功能和新语法,其中一个是我最常用的 async/await。我现在也经常在用,有时在异步处理数组的里数据时会出现这个问题。

异步循环

如何在循环中使用 await ?让我们编写异步函数并 await 每个任务。

async function processArray(array) {
  array.forEach(item => {
    // define synchronous anonymous function
    // IT WILL THROW ERROR!
    await func(item);
  })
}

这段代码会出现一个语法错误,因为我们不能在同步函数里使用 await 。“processArray”是一个异步函数,但是我们在这个匿名函数里用到的 forEach 是同步的。

1.不需要等待结果

如何修复之前的问题?我们可以这样异步定义匿名函数:

async function processArray(array) {
  array.forEach(async (item) => {
    await func(item);
  })
  console.log('Done!');
}

但是 forEach 不会等到所有的步骤都完成,它只会执行任务和执行下一步。作为证明我们可以这样写一个简单例子:

function delay() {
  return new Promise(resolve => setTimeout(resolve, 300));
}

async function delayedLog(item) {
  // notice that we can await a function
  // that returns a promise
  await delay();
  console.log(item);
}
async function processArray(array) {
  array.forEach(async (item) => {
    await delayedLog(item);
  })
  console.log('Done!');
}

processArray([1, 2, 3]);

结果输出为:

Done!
1
2
3

如果不需要等结果这样写是ok的,但是在大多数案例里这不是个很好的逻辑。

2. 线性处理数组

要等待结果,我们应该返回到老式的 for 循环,但这一次为了更好的可读性我们可以使用现代写法 for..of。

sync function processArray(array) {
  for (const item of array) {
    await delayedLog(item);
  }
  console.log('Done!');
}

结果输出:

1
2
3
Done!

该代码将依次处理每一项。但是我们可以使用并行运行。

3.并行处理数组

我们可以稍微修改下代码然后并行运行:

async function processArray(array) {
  // map array to promises
  const promises = array.map(delayedLog);
  // wait until all promises are resolved
  await Promise.all(promises);
  console.log('Done!');
}

这段代码将并行运行许多delayLog 任务。但是对于非常大的数组要小心(并行的任务太多对CPU或内存来说可能比较吃力)。

也不要混淆“并行”与真正的线程和并行。该代码不能保证真正的并行执行。这取决于您的 item函数(在本演示中是delayedLog)。网络请求、webworker 和其他一些任务可以并行执行。

感谢阅读!

出处:Anton Lavrenov Blog

上一篇下一篇

猜你喜欢

热点阅读