博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
forEach,for...of,map与asycn/await
阅读量:7232 次
发布时间:2019-06-29

本文共 4299 字,大约阅读时间需要 14 分钟。

遍历数组forEach,for..of,map方法传递异步函数时遇到了一些奇怪的问题。查看了几篇文章,总结一下看到的内容:

If you want to read the files in sequence, you cannot use forEach indeed. Just use a modern for … of loop instead, in which await will work as expected:

async function printFiles () { const files = await getFilePaths(); for (const file of files) {   const contents = await fs.readFile(file, 'utf8');   console.log(contents); }}复制代码

for ...of遍历数组可以得到按顺序执行await期待得到的结果

在chrome console中执行结果?

async function ddd(){	let a = [0,1,2,3,4,5,6,7,8,9];	for(let aa of a){		await setTimeout(function(){
console.log(aa)},1000-aa*100); }}执行结果:9876543210复制代码

Using Babel will transform async/await to generator function and using forEach means that each iteration has an individual generator function, which has nothing to do with the others. so they will be executed independently and has no context of next() with others. Actually, a simple for() loop also works because the iterations are also in one single generator function.

If you want to read the files in parallel, you cannot use forEach indeed. Each of the async callback function calls does return a promise, but you're throwing them away instead of awaiting them. Just use map instead, and you can await the array of promises that you'll get with Promise.all:

async function printFiles () {  const files = await getFilePaths();  await Promise.all(files.map(async (file) => {    const contents = await fs.readFile(file, 'utf8')    console.log(contents)  }));}复制代码

使用Promise.all(map())可以并行执行并得到一个promise数组

chrome console执行结果:?

async function ddd(){	let a = [0,1,2,3,4,5,6,7,8,9];	await Promise.all(a.map(async (aa)=>{
await setTimeout(function(){
console.log(aa)},1000-aa*100)}));}执行结果:9876543210复制代码

To me using Promise.all() with map() is a bit difficult to understand and verbose, but if you want to do it in plain JS that's your best shot I guess. If you don't mind adding a module, I implemented the Array iteration methods so they can be used in a very straightforward way with async/await. An example with your case:

const { forEach } = require('p-iteration');const fs = require('fs-promise');async function printFiles () {  const files = await getFilePaths();  await forEach(files, async (file) => {    const contents = await fs.readFile(file, 'utf8');    console.log(contents);  });}printFiles()复制代码

引入p-iteration模块也可以解决问题

Instead of Promise.all in conjunction with Array.prototype.map (which does not guarantee the order in which the Promises are resolved), I use Array.prototype.reduce, starting with a resolved Promise:

async function printFiles () {  const files = await getFilePaths();  await files.reduce(async (promise, file) => {    // This line will wait for the last async function to finish.    // The first iteration uses an already resolved Promise    // so, it will immediately continue.    await promise;    const contents = await fs.readFile(file, 'utf8')    console.log(contents)  }, Promise.resolve());}复制代码

利用数组的reduce()方法传入一个resolved promise作为初始值,链式执行promise,异步函数会按顺序执行且每次只执行一个

chrom console执行:?

async function ccc () {  const files = [0,1,2,3,4,5,6,7,8,9];  await files.reduce(async (promise, file) => {    // This line will wait for the last async function to finish.    // The first iteration uses an already resolved Promise    // so, it will immediately continue.    await promise;    const contents = await setTimeout(function(){
console.log(file),1000-file*100}) console.log(contents) }, Promise.resolve());}执行结果:0123456789复制代码

reduce()方法介绍:

The reduce() method executes a reducer function (that you provide) on each member of the array resulting in a single output value.

syntax: arr.reduce(callback[, initialValue])

description: reduce() executes the callback function once for each element present in the array, excluding holes in the array, receiving four arguments:

  • accumulator
  • currentValue
  • currentIndex
  • array

The first time the callback is called, accumulator and currentValue can be one of two values. If initialValue is provided in the call to reduce(), then accumulator will be equal to initialValue, and currentValue will be equal to the first value in the array. If no initialValue is provided, then accumulator will be equal to the first value in the array, and currentValue will be equal to the second.

然而越看越晕,并没有搞懂这个问题?

参考文章链接:

转载地址:http://ekjfm.baihongyu.com/

你可能感兴趣的文章
Linux命令学习1
查看>>
SCOM2012功能测试(29)—查看-Diagnostics
查看>>
mysql 1449 : The user specified as a definer (\'root\'@\'%\') does not exist 解决方法
查看>>
C# 有符号整数 无符号整数
查看>>
Shell脚本中的 测试开关 和 特殊参数
查看>>
C语言小程序-基于链表的学生信息管理
查看>>
搜索二叉树
查看>>
【java】java学习之路-01-Linux基础(一)
查看>>
GridView中字符串太长处理方式
查看>>
20175318 2018-2019-2 实验二《Java面向对象程序设计》实验报告
查看>>
Fiddler (二) Script 用法
查看>>
angularjs4+ionic3集成搭建
查看>>
jQuery动画
查看>>
网络打印机拒绝访问,无法连接处理方法汇总
查看>>
SQL Server 表压缩
查看>>
HDU-3549 Flow Problem 简单最大流
查看>>
利用Ajax无刷新更新rss阅读
查看>>
Arch Linux 安装 ibus 五笔输入法备忘录
查看>>
第38周星期二
查看>>
hdu1166(单点更新,区间求和)
查看>>