JS Array.map方法内异步方法无法同步执行

问题:

JS Array.map方法内异步方法无法同步执行

场景:
我们在使用map来设置每一项值的时候,涉及到异步操作,就会出现问题。
按照常规,重现出一种情形。
假设我要使用map对每一项值进行操作,其中涉及到异步操作(此处使用演示来模拟),在简短延时后将值设置为10。

我们理想中ret的值是[10,10,10,10,10]

(async () => {
  let arr = [1,2,3,4,5]
  let res = await arr.map(async (item) => {
    console.log(item+'执行')
    // map并发执行
    await new Promise(resolve=>{
        setTimeout(()=>{
          console.log(item+'结束');
          resolve();
        },2000)
    })
    return 10
  })
  console.log(res)
})()

使用node执行一下发现

在这里插入图片描述

解决

1.使用for..of或者其他循环替代

因为我们无法改变map函数内部的代码,使用Promise同步化异步操作。

所以我们只能自己遍历出所有内容,进行逐一操作。

2.使用promise.all

let arr1 = [1,2,3,4,5]
let res = await Promise.all(arr.map(async (item) => {
	await new Promise(resolve=>{
        setTimeout(() => {
          console.log(item + '内结束');
          resolve();
        }, 2000)
    })
    return 10
}));
console.log(res)

原因剖析

map函数的原理是:

循环数组,获取每项数组对应的内容,

调用map函数传入的方法,获取数组的新内容,

将新内容push到新数组,最后返回。

map函数是同步执行的,所以循环每一项时,到给新数组值时,都是同步操作。

上面返回数组中都是Promise对象,因为他们还没执行完成就赋值了。

为了更加了解为什么,我们可以自己写一个map方法。

Array.prototype.mymap = async function (fun) {
  let ret = []
  for(let item of this) {
    // 遍历
    // 等待传入的异步执行完成再push
    item = await fun(item)
    ret.push(item)
  }
  // 全部完成
  return ret
};

(async () => {
  let arr1 = [1,2,3,4,5]
  let res = await arr1.mymap(async (item)=>{
    // 异步操作
    await new Promise(resolve=>{
        setTimeout(() => {
          console.log(item + '内结束');
          resolve();
        }, 2000)
    })
    return 10
  })

  console.log(res)
})()

总结

要运用最合适的方法处理最合适的问题,才能达到事半功倍~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值