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


Posted in Javascript onApril 15, 2019

这是重学 JS 系列的第三篇文章,写这个系列的初衷也是为了夯实自己的 JS 基础或者了解一些之前不知道的东西。既然是重学,肯定不会从零开始介绍一个知识点,如有遇到不会的内容请自行查找资料。

不知道你有没有写过类似的代码,反正以前我是写过

function test() {
 let arr = [3, 2, 1]
 arr.forEach(async item => {
  const res = await fetch(item)
  console.log(res)
 })
 console.log('end')
}

function fetch(x) {
 return new Promise((resolve, reject) => {
  setTimeout(() => {
   resolve(x)
  }, 500 * x)
 })
}

test()

我当时期望的打印顺序是

3
2
1
end

 结果现实与我开了个玩笑,打印顺序居然是

end
1
2
3

为什么?

其实原因很简单,那就是 forEach 只支持同步代码。

我们可以参考下 Polyfill 版本的 forEach,简化以后类似就是这样的伪代码

while (index < arr.length) {
  // 也就是我们传入的回调函数
  callback(item, index)
}

从上述代码中我们可以发现,forEach 只是简单的执行了下回调函数而已,并不会去处理异步的情况。并且你在 callback 中即使使用 break 也并不能结束遍历。

怎么解决?

一般来说解决的办法有两种。

第一种是使用 Promise.all 的方式

async function test() {
 let arr = [3, 2, 1]
 await Promise.all(
  arr.map(async item => {
   const res = await fetch(item)
   console.log(res)
  })
 )
 console.log('end')
}

这样可以生效的原因是 async 函数肯定会返回一个 Promise 对象,调用 map 以后返回值就是一个存放了 Promise 的数组了,这样我们把数组传入 Promise.all 中就可以解决问题了。但是这种方式其实并不能达成我们要的效果,如果你希望内部的 fetch 是顺序完成的,可以选择第二种方式。

第一种方法是使用 for...of

async function test() {
 let arr = [3, 2, 1]
 for (const item of arr) {
  const res = await fetch(item)
  console.log(res)
 }
 console.log('end')
}

这种方式相比 Promise.all 要简洁的多,并且也可以实现开头我想要的输出顺序。

但是这时候你是否又多了一个疑问?为啥 for...of 内部就能让 await 生效呢。

因为 for...of 内部处理的机制和 forEach 不同,forEach 是直接调用回调函数,for...of 是通过迭代器的方式去遍历。

async function test() {
 let arr = [3, 2, 1]
 const iterator = arr[Symbol.iterator]()
 let res = iterator.next()
 while (!res.done) {
  const value = res.value
  const res1 = await fetch(value)
  console.log(res1)
  res = iterator.next()
 }
 console.log('end')
}

最后
以上就是本篇文章的全部内容了,如果你还有什么疑问欢迎在评论区与我互动。

我所有的系列文章都会在我的 Github 中最先更新,有兴趣的可以关注下。今年主要会着重写以下三个专栏

重学 JS
React 进阶
重写组件

以上所述是小编给大家介绍的为啥await 不能用在 forEach 中详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
js 屏蔽鼠标右键脚本附破解方法
Dec 03 Javascript
Js使用WScript.Shell对象执行.bat文件和cmd命令
Dec 18 Javascript
jQuery学习笔记之基础中的基础
Jan 19 Javascript
Python脚本后台运行的几种方式
Mar 09 Javascript
Javascript非构造函数的继承
Apr 27 Javascript
Fullpage.js固定导航栏-实现定位导航栏
Mar 17 Javascript
HTML Table 空白单元格补全的简单实现
Oct 13 Javascript
AngularJS+Bootstrap实现多文件上传与管理
Nov 08 Javascript
解决angularjs中同步执行http请求的方法
Aug 13 Javascript
JS中appendChild追加子节点无效的解决方法
Oct 14 Javascript
Vue 使用beforeEach实现登录状态检查功能
Oct 31 Javascript
微信小程序实现加入购物车滑动轨迹
Nov 18 Javascript
你不知道的Vue技巧之--开发一个可以通过方法调用的组件(推荐)
Apr 15 #Javascript
详解JavaScript中的强制类型转换
Apr 15 #Javascript
一个小时快速搭建微信小程序的方法步骤
Apr 15 #Javascript
详解从0开始搭建微信小程序(前后端)的全过程
Apr 15 #Javascript
ES6知识点整理之模块化的应用详解
Apr 15 #Javascript
详解如何运行vue项目
Apr 15 #Javascript
vue单页面在微信下只能分享落地页的解决方案
Apr 15 #Javascript
You might like
MySql中正则表达式的使用方法描述
2008/07/30 PHP
ajax php 实现写入数据库
2009/09/02 PHP
php在文件指定行中写入代码的方法
2012/05/23 PHP
PHP并发查询MySQL的实例代码
2017/08/09 PHP
PHP与Web页面的交互示例详解一
2020/08/04 PHP
phpstorm激活码2020附使用详细教程
2020/09/25 PHP
jQuery 一个图片切换的插件
2011/10/09 Javascript
THREE.JS入门教程(2)着色器-上
2013/01/24 Javascript
JavaScript等比例缩放图片控制超出范围的图片
2013/08/06 Javascript
JS弹出层的显示与隐藏示例代码
2013/12/27 Javascript
KnockoutJS 3.X API 第四章之click绑定
2016/10/10 Javascript
JavaScript中的call和apply的用途以及区别
2017/01/11 Javascript
es6系列教程_ Map详解以及常用api介绍
2017/09/25 Javascript
浅谈React + Webpack 构建打包优化
2018/01/23 Javascript
vue项目打包后打开页面空白解决办法
2018/06/29 Javascript
vue中音频wavesurfer.js的使用方法
2020/02/20 Vue.js
JavaScript实现答题评分功能页面
2020/06/24 Javascript
python数据结构树和二叉树简介
2014/04/29 Python
python 3.7.0 安装配置方法图文教程
2018/08/27 Python
详解如何从TensorFlow的mnist数据集导出手写体数字图片
2019/08/05 Python
python多线程案例之多任务copy文件完整实例
2019/10/29 Python
redis数据库及与python交互用法简单示例
2019/11/01 Python
在python下实现word2vec词向量训练与加载实例
2020/06/09 Python
Python改变对象的字符串显示的方法
2020/08/01 Python
Ubuntu权限不足无法创建文件夹解决方案
2020/11/14 Python
Python获取指定网段正在使用的IP
2020/12/14 Python
Python列表元素删除和remove()方法详解
2021/01/04 Python
利用CSS3的特性改变文本选中时的颜色
2013/09/11 HTML / CSS
金融专业个人求职信
2013/09/22 职场文书
金融系毕业生自荐书
2014/07/08 职场文书
国庆节演讲稿范文2014
2014/09/19 职场文书
2015年教务主任工作总结
2015/07/22 职场文书
2017元旦晚会开幕词
2016/03/03 职场文书
学习师德师风的心得体会(2篇)
2019/10/08 职场文书
元素水平垂直居中的方式
2021/03/31 HTML / CSS
Win11 BitLocker 驱动器加密
2022/04/19 数码科技