async await结合forEach使用注意

场景:对一个对象或者数组遍历,其中一个值满足条件时请求接口,得到数据后进行后续代码操作

1.forEach回调函数直接结合async await使用,并不能将循环中的异步请求转为同步,得不到正常结果

Object.keys(propsAccountInfo).forEach(async (v) => {
        if (v === "bankId" && propsAccountInfo[v]) {
          await this.getBankBranchList(propsAccountInfo[v]);
          this.accountForm[v] = propsAccountInfo[v];
        }
      });

2.改用for循环,能正常得到结果

for (let i = 0; i < Object.keys(propsAccountInfo).length; i++) {
        if (
          Object.keys(propsAccountInfo)[i] === "bankId" &&
          propsAccountInfo[Object.keys(propsAccountInfo)[i]]
        ) {
          await this.getBankBranchList(
            propsAccountInfo[Object.keys(propsAccountInfo)[i]]
          );
        }
}
// 上面代码异步请求接口以后再带入数据 Object.keys(propsAccountInfo).forEach((v) => { this.accountForm[v] = propsAccountInfo[v];
    });

原因分析:

for:

const report = async () => {
    for (let i = 0, len = arr.length; i < len; i++) {
        await asyncFn(arr[i]);
    }
};

forEach

const report = async () => {
    arr.forEach(async (item) => {
        await asyncFn(item);
    });
};
//相当于:
const report = async () => {
    const asyncFnWrap = async (item) => {
      await asyncFn(item);
    };
    for (let i = 0, len = arr.length; i < len; i++) {
        asyncFnWrap(arr[i], i);
    }
};

第一个for循环的 asyncFn 要await返回后才继续执行,所以是顺序执行,而第二个的 asyncFnWrap 不会阻塞循环。

实际上还是forEach内部实现不支持await的问题:

Array.prototype.forEach = function (callback) {
  // this represents our array
  for (let index = 0; index < this.length; index++) {
    // We call the callback for each entry
    callback(this[index], index, this)
  }
}

扩展一下

Array.prototype.forEachAsync = async function (fn) {
    for (let t of this) { await fn(t) }
}

Array.prototype.forEachAsyncParallel = async function (fn) {
    await Promise.all(this.map(fn));
}

 

参考来源:https://imweb.io/topic/5b3b7d624d378e703a4f4437

posted @ 2020-08-01 15:10  盼星星盼太阳  阅读(386)  评论(0编辑  收藏  举报