重学 JS:为啥 await 不能用在 forEach 中详解

yizhihongxing

当我们使用 async/await 来处理异步函数时,有可能会遇到在 forEach 循环中使用 await 语句,导致 await 处理不完整的问题,这是因为 forEach 循环的特殊性导致的。

问题

forEach 循环是 JavaScript 提供的一种遍历数组的方式,常用于对数组中的每一项进行操作,语法如下:

array.forEach(callback(currentValue [, index [, array]]) {
  // 处理逻辑
}[, thisArg]);

其中 callback 是一个函数,用于处理数组中的每一项,currentValue 是数组中的当前项,index 是当前项的索引位置,array 是数组本身,thisArg 是执行 callback 时的 this 值,默认是 undefined

forEach 中使用 await 的问题就在于,await 只会等待 Promise 对象完成,然而 forEach 并不会等待回调函数完成,而是在每次调用回调函数之后立即执行下一轮循环,导致 await 处理不完整。

以下是一个示例:

const delay = ms => new Promise(resolve => setTimeout(resolve, ms));

const array = [1, 2, 3];
array.forEach(async item => {
  await delay(1000);
  console.log(item);
});

console.log('done');

在这个示例中,我们使用了 delay 函数来延迟 1 秒钟,然后在 forEach 循环中使用 await 来等待这个延迟。但是,我们会发现 done 被先输出了,然后才是数组中的每一项,这是因为 forEach 循环不会等待回调函数的完成。

解决方案

解决这个问题的方法之一是使用 for...of 循环,因为 for...of 会等待每一个循环体内的异步操作完成,而不是像 forEach 那样不等待直接执行下一次循环。

以下是一个 for...of 的示例:

const delay = ms => new Promise(resolve => setTimeout(resolve, ms));

const array = [1, 2, 3];
for (const item of array) {
  await delay(1000);
  console.log(item);
}

console.log('done');

在这个示例中,我们使用了 for...of 循环,将数组中的每一项作为变量 item,然后使用 await 语句等待 delay 函数的延迟完成。这个示例会正确输出数组中的每一项,然后输出 done,说明 for...of 循环可以正确地等待异步操作完成。

另外一种解决方案是使用 Promise.all 来并行执行异步任务,然后使用 map 方法将每个任务映射为一个 Promise 对象,代码如下:

const delay = ms => new Promise(resolve => setTimeout(resolve, ms));

const array = [1, 2, 3];
await Promise.all(array.map(async item => {
  await delay(1000);
  console.log(item);
}));

console.log('done');

在这个示例中,我们使用 Promise.all 来并行执行异步任务,然后使用 map 方法将每个任务映射为一个 Promise 对象,然后使用 await 语句等待所有 Promise 对象的完成。这个示例也会正确输出数组中的每一项,然后输出 done

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:重学 JS:为啥 await 不能用在 forEach 中详解 - Python技术站

(1)
上一篇 2023年6月8日
下一篇 2023年6月8日

相关文章

  • 简述pm2常用命令集合及配置文件说明

    下面我给你详细讲解“简述PM2常用命令集合及配置文件说明”的完整攻略。 一、PM2常用命令集合 在使用PM2时,经常需要用到一些常用命令,以下是一些常见命令: 1. pm2 start 启动一个进程启动文件。示例: pm2 start index.js 2. pm2 list 显示所有已经启动的进程列表,示例: pm2 list 3. pm2 restart…

    node js 2023年6月8日
    00
  • Node.js控制台彩色输出的方法与原理实例详解

    对于Node.js控制台彩色输出的方法与原理,这是一篇基础又实用的教程。接下来将详细讲解。 标题一:控制台彩色输出 Node.js作为一款流行的服务器端JavaScript环境,其强大的NPM(Node.js Package Manager)体系和灵活的模块化机制,让前端开发者强势入驻后端开发领域。在Node.js中,颜色在命令行终端的界面上,可以帮助我们更…

    node js 2023年6月8日
    00
  • 利用node.js如何搭建一个简易的即时响应服务器

    要搭建一个简易的即时响应服务器,可以使用node.js结合一些常见的包(例如Express、Socket.io等)来实现。以下是具体攻略: 第一步:安装Node.js 首先需要下载安装Node.js,可以去官网下载可执行文件,安装完成后在终端或命令行窗口中输入以下指令,如果正确输出版本号则说明安装成功: node -v 第二步:初始化项目 接下来,需要初始化…

    node js 2023年6月8日
    00
  • JS大坑之19位数的Number型精度丢失问题详解

    JS大坑之19位数的Number型精度丢失问题详解 问题描述 在JavaScript中,Number类型最大安全整数为$2^{53}-1$,也就是9007199254740991。然而在某些情况下,用Number类型表示的19位数却会产生精度丢失的问题。例如以下代码: console.log(9999999999999999999); // 10000000…

    node js 2023年6月8日
    00
  • React diff算法面试考点超详细讲解

    React diff算法是React性能优化中的一个重要环节,它在React Virtual DOM中使用,用于在进行新旧Virtual DOM节点的比较时,将节点差异找出来并进行只更新需要更新的部分,让页面渲染更加高效。在面试中,相关考点会非常重要,本文将从以下几个方面分别进行讲解。 一、React diff算法过程 React diff算法的具体过程如下…

    node js 2023年6月8日
    00
  • 从Node.js 转到 Go平台

    从Node.js转到Go平台需要掌握以下技能点: 1.了解Go语言的基础语法和特性 2.掌握Go语言的标准库和常用的第三方工具库 3.学习如何使用Go语言的并发模型 4.理解如何优化Go语言应用程序的性能 下面是从Node.js转到Go平台的完整攻略: 1. 学习Go语言的基础语法和特性 了解Go语言的基础语法和特性是学习Go语言的第一步。你需要学习Go语言…

    node js 2023年6月8日
    00
  • 从0搭建vue-cli4脚手架

    下面详细讲解从0搭建vue-cli4脚手架的完整攻略。 简介 Vue.js是一个渐进式JavaScript框架,旨在实现简单、易学、高效、灵活的开发方式。Vue-cli是vuejs官方提供的一个基于Webpack的脚手架工具,可以快速搭建SPA应用程序的基本开发框架,是Vuejs的标准构建工具,也是Vue项目开发的标配。 本文将详细讲述如何从0开始搭建Vue…

    node js 2023年6月8日
    00
  • nodejs 后缀名判断限制代码

    下面是关于“node.js 后缀名判断限制代码”的详细攻略: 1. 问题背景 在 Node.js 的文件操作中,往往需要限制一个目录下的文件只能读取指定的后缀名,其他后缀名的文件不能读取。这种情况下,我们需要编写相关的代码进行判断和限制。 2. 解决方案 使用 Node.js 的 fs 模块可以实现对文件的读取和限制。使用 fs.readdir 方法读取指定…

    node js 2023年6月8日
    00
合作推广
合作推广
分享本页
返回顶部