当前位置: 首页 > news >正文

forEach,for...of,map与asycn/await

遍历数组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);
	}
}
执行结果:
9
8
7
6
5
4
3
2
1
0
复制代码

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)}));
}
执行结果:
9
8
7
6
5
4
3
2
1
0
复制代码

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());
}
执行结果:
0
1
2
3
4
5
6
7
8
9
复制代码

reduce()方法介绍:developer.mozilla.org/en-US/docs/…

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.

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

参考文章链接:

stackoverflow.com/questions/3…

thecodebarbarian.com/basic-funct…

medium.com/@antonioval…

相关文章:

  • Synchronized 关键字使用、底层原理、JDK1.6 之后的底层优化以及 和ReenTrantLock 的对比...
  • jchdl - GSL实例 - DFlipFlop(D触发器)
  • webgl滤镜--会呼吸的痛
  • 区块链入门教程btcpool矿池源码分析环境搭建
  • 镁客网每周硬科技领域投融资汇总(10.21-10.27),AI芯片创企Syntiant获英特尔等头部企业投资...
  • zabbix介绍
  • 如何做需求分析
  • Netty Channel源码分析
  • VPC配置案例
  • 使用CefSharp的一些需要注意的点
  • Kibana配置logstash,报表一体化
  • 读程序员,你焦虑吗有感。
  • 利用github和git命令,将本地项目共享到服务器上——第二章
  • SQL/My sql
  • 微信小程序点击图片放大预览
  • - C#编程大幅提高OUTLOOK的邮件搜索能力!
  • Cookie 在前端中的实践
  • django开发-定时任务的使用
  • eclipse的离线汉化
  • es6--symbol
  • JavaScript 一些 DOM 的知识点
  • Linux各目录及每个目录的详细介绍
  • MYSQL 的 IF 函数
  • Netty 4.1 源代码学习:线程模型
  • Vue全家桶实现一个Web App
  • Vue源码解析(二)Vue的双向绑定讲解及实现
  • 阿里云爬虫风险管理产品商业化,为云端流量保驾护航
  • 计算机常识 - 收藏集 - 掘金
  • 聚簇索引和非聚簇索引
  • 老板让我十分钟上手nx-admin
  • 那些被忽略的 JavaScript 数组方法细节
  • 软件开发学习的5大技巧,你知道吗?
  • 设计模式(12)迭代器模式(讲解+应用)
  • 微信公众号开发小记——5.python微信红包
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • 硬币翻转问题,区间操作
  • 智能合约Solidity教程-事件和日志(一)
  • 看到一个关于网页设计的文章分享过来!大家看看!
  • 阿里云API、SDK和CLI应用实践方案
  • 容器镜像
  • 专访Pony.ai 楼天城:自动驾驶已经走过了“从0到1”,“规模”是行业的分水岭| 自动驾驶这十年 ...
  • ​TypeScript都不会用,也敢说会前端?
  • ​如何防止网络攻击?
  • #define,static,const,三种常量的区别
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • (1) caustics\
  • (1)(1.13) SiK无线电高级配置(五)
  • (175)FPGA门控时钟技术
  • (C#)Windows Shell 外壳编程系列9 - QueryInfo 扩展提示
  • (C语言版)链表(三)——实现双向链表创建、删除、插入、释放内存等简单操作...
  • (Redis使用系列) Springboot 使用Redis+Session实现Session共享 ,简单的单点登录 五
  • (附源码)ssm高校升本考试管理系统 毕业设计 201631
  • (七)理解angular中的module和injector,即依赖注入
  • (转)ABI是什么
  • (转)IIS6 ASP 0251超过响应缓冲区限制错误的解决方法