JS循环遍历中使用异步

参考:JS中如何循环遍历顺序执行异步操作_js异步循环_ienyh的博客-CSDN博客

JS循环遍历中使用异步

对于同步顺序执行异步操作,并且每次异步操作都需要随着循环顺序执行

1、对于forEach来说(慎用)

forEach 方法是同步的,也就是 forEach 的回调函数都是同步调用的,在 forEach 的回调里进行异步操作,每次遍历进行的这些异步操作会并行执行。它的每个迭代都会在前一个迭代完成之后立即执行。因此,在 forEach 中使用异步操作是不可能的,因为它将导致执行流阻塞,而且无法保证异步操作的完成顺序。

//定义一个异步函数
const foo1 = (i:any)=>{
  return new Promise((resolve, reject) => {
    setTimeout(() =>{
      console.log(i);
      resolve(i)

    },1000)
    
  })
}
const arr = [1,2,3,4,5]
const b = () =>{
  arr.forEach(async e => {
    console.log(e);
    
    await foo1(e)
  });
}
b(); // 1 2 3 4 5 1 2 3 4 5

2、对于for循环来说(不推荐)

for方法是异步的,也就是每次循环都能顺序执行异步操作
缺点:fo每次循环的作用域是用一个,可能会导致异步操作未结束就进入到下一个迭代中

//定义一个异步函数
const foo1 = (i:any)=>{
  return new Promise((resolve, reject) => {
    setTimeout(() =>{
      console.log(i);
      resolve(i)

    },1000)
    
  })
}
const arr = [1,2,3,4,5]
async function a() {
  for (var i = 0; i < arr.length; i++) {
    console.log(arr[i]);
    
    await foo1(arr[i])
  }
}
a() // 输出:1 1 2 2 3 3 4 4 5 5

3、对于for of 循环(推荐)

其是ES6引入的一种新的循环接口,用于遍历可迭代对象,例如数组、Map和Set等。在使用异步操作时,for…of循环是最推荐的一种方式,因为它每次迭代都会创建一个新的作用域,可以保证异步操作的独立性和安全性。

它可以等异步执行结束后才进入下一个迭代

async function processData(data) {
  for (const item of data) {
    await doAsyncOperation(item);
  }
}

async function doAsyncOperation(item) {
  return new Promise((resolve, reject) => {
    // 异步操作代码
  });
}

在这个例子中,processData 函数使用 for...of 循环来遍历数据,并在每个迭代中等待异步操作完成。doAsyncOperation 函数返回一个 Promise,以便 processData 函数可以等待它完成。这样,异步操作的执行顺序就得到了保证。

4、同时可以用Promise.all来

async function processData(data) {
  const promises = data.map(doAsyncOperation);
  await Promise.all(promises);
}

async function doAsyncOperation(item) {
  return new Promise((resolve, reject) => {
    // 异步操作代码
  });
}

在这个例子中,processData 函数使用 map 方法来创建一个包含所有异步操作 Promise 的数组,并在数组上调用 Promise.all 方法。Promise.all 方法将等待所有异步操作完成,然后将它们的结果作为数组返回。这样,所有异步操作都将以并行方式执行。

总结:所以对于循环中调用异步操作的需求,慎用forEach(同步),不推荐for循环(每次迭代身处同一作用域),推荐使用for of以及promise.all二种方式

猜你喜欢

转载自blog.csdn.net/qq_21473443/article/details/130772416