循环中的异步请求结果在循环外使用问题

场景:在一个for循环中执行异步请求,请求结果最终需要在循环外部使用。

let targetData = [];
let originData = [1,2,3];
for ( let i = 0; i < originData.length; i++  ) { 
  // 这里执行异步ajax 我们用setTimeout模拟
  setTimeout(() => {
    targetData.pusn(i);
  },0)
}
console.log(targetData); // []

由于异步代码执行是在主栈代码执行结束之后再执行,因此console.log(targetData)在执行的时候for循环内部的异步代码并没有执行。因此也就在外部获取不到我们想要的数据。

解决方案:
1. 使用Promise.all()进行请求并发处理

let targetData = [];
let originData = [1,2,3];
let promises = originData.map((item) =>{
  return new Promise((resolve, reject) => {
    // 异步ajax 用setTimeout模拟
    setTimeout(() => {
      targetData.push(item);
      resolve();
    },0)
  })
})
Promise.all(promises).then(() => {
  console.log(targetData); // [1, 2, 3]
})

将每次的异步逻辑装在promises数组中。然后调用Promise.all()进行并行请求,然后就能在Promise.all()的then回调里获取到我们想要的值。但是这样会有一个问题,就是当promises数组中其中一个请求挂掉了,那么永远也不能在Promise.all()的then回调里获取到数据。具体处理方法,在我的这篇文章里有叙述Javascript知识零散学习(面试篇)。

2. 使用async / await进行请求逐个处理

let targetData = [];
let originData = [1,2,3];
function getAsyncData(i){
  return new Promise((resolve,reject) => {
    setTimeout(() => {
      targetData.push(i);
      resolve();
    }, 0)
  })
}

async function initalRequest(){
  for(let i = 0; i < originData.length; i++){
    await getAsyncData(originData[i])
  }
}

initalRequest().then(() => {
  console.log(targetData); // [1,2,3];
})

这种方法逐一对异步请求进行处理,执行效率相对第一种较低,如果其中有一个请求挂掉,那么也不会在initalRequest()的then方法中获取数据,这个时候可以在getAsyncData方法中的Promise中进行catch捕获,和上面处理错误形式一样。这样就能正常获取到数据了。

你可能感兴趣的:(循环中的异步请求结果在循环外使用问题)