返回

巧用async/await,告别forEach异步烦恼

前端

在繁忙的JavaScript世界中,异步编程已成为一种常态,它允许我们在不阻塞主线程的情况下执行耗时的操作。然而,当涉及到遍历数组并针对每个元素执行异步任务时,我们经常会遇到一些挑战。

在这种情况下,forEach 方法似乎是一个显而易见的选择,因为它提供了一种简单的方法来遍历数组。但是,当我们将await 引入forEach 时,事情就开始变得复杂起来。

awaitforEach 中无效

场景 :现有一个数组,要依次循环去请求拿到结果。

错误示例

const asyncForEach = async (array, callback) => {
  array.forEach(async (item) => {
    const result = await callback(item);
    console.log(result);
  });
};

通过控制台发现,代码并没有按照预期依次打印出来,而是等待一下,全部打印出来。

问题根源

forEach 本身是一个同步方法,它将依次调用回调函数。然而,当我们在回调函数中使用await 时,forEach 会立即执行所有回调,并等待所有异步任务完成后才继续执行。

解决方案:

为了解决此问题,我们可以使用async/awaitfor...of 循环的组合:

const asyncForEach = async (array, callback) => {
  for (const item of array) {
    const result = await callback(item);
    console.log(result);
  }
};

for...of 循环是一个异步迭代器,它会等待每个await 操作完成,然后再继续执行。这样,asyncForEach 函数将依次执行每个异步任务,并立即打印结果。

其他技巧

1. 控制并发

通过限制并发请求的数量,我们可以优化性能并防止服务器过载。例如:

const asyncForEach = async (array, callback, limit = 5) => {
  const requests = [];
  for (const item of array) {
    requests.push(callback(item));
  }
  await Promise.all(requests.slice(0, limit));
  return await Promise.all(requests.slice(limit));
};

2. 错误处理

在异步操作中处理错误至关重要。我们可以使用try...catch 块或Promise.catch() 来捕获错误并防止应用程序崩溃。

总结

通过巧妙地使用async/awaitfor...of 循环,我们可以克服forEachawait 的限制,从而有效地实现异步遍历。记住,理解异步编程的原理并正确使用这些工具,对于构建响应迅速且可靠的JavaScript应用程序至关重要。