添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第16天, 点击查看活动详情

问题描述: for循环,再把循环出来的结果再进行二次请求,这就导致一个问题

请求结果返回顺序不一致

原因: 异步请求会把回调事件放入微任务事件队列,宏任务执行完毕再执行微任务,具体参考事件队列机制

提示:循环不能是异步的,for循环是同步任务,内部的异步任务会在for循环执行完成后执行

解决方法1:

通过map方法进行循环请求

将异步请求方法封装起来,返回一个promise

这样将会返回一个具有多个promise的数组

通过promise.all()方法把promise包装成一个新的promise实例

解决方法2: 循环中使用递归。使用递归函数在事件循环的单独轮次中执行迭代,在事件循环的单独轮次中执行递归,不会导致调用栈溢出。

()事件循环的每个轮次中调用其他事件处理程序的调用栈最初是空的)

这个问题涉及事件循环:

所有同步任务都在主线程上执行,形成一个“执行栈”

主线程之外,还存在一个“任务队列”,只要异步任务有了结果,就在“任务队列”中放置一个事件

一旦执行栈的所有同步任务完成,系统就读取“任务队列”对应异步任务,结束等待状态,进入执行栈,开始执行(执行异步回调)

主线程不断重复(3)步骤

解决方式一 :Promise.all

function ajax() {
    let data = [{ name: '小明', age: 22 }, { name: '小红', age: 18 }]
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve(data)
      }, 200)
// 创建Promise方法
function createPromise() {
  let promise = new Promise((resolve, reject) => {
    //将业务接口的返回值,resolve进去
      ajax().then((res) => {
        resolve(res)
    return promise
function run() {
    let userList = [{ id: 1 }, { id: 2 }];
    let list = [];
    let resList = [];
    userList.forEach((item) => {
      list.push(createPromise())
    Promise.all(list).then((res) => {
      resList = res
run()

Promise.all得等所有请求成功,才能返回,会遇到阻塞问题

Promise.all得等所有请求响应,响应时间太长问题

更优的解决办法:递归调用接口

//模拟ajax请求
function ajax(length) {
    let data = [{ name: '小明', age: 22 }, { name: '小红', age: 18 }]
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        // resolve(data)
        // let newData = data.map(item=>{  return {...item,age:item.age*length}  })
        let newData = data.map(item=>item.age*length )
        resolve(newData)
      }, 200)
 // 递归终止条件,数组长度小于
  async function run(length, arr) {
    const res = await ajax(length);
    arr.push(res);
    console.log('res',length,res)
    if (length> 1) {
      await run(length- 1, arr)
    console.log('afer res',res)
    return arr
  async function getResult() {
    let userList = [{ id: 1 }, { id: 2 }];
    let res = await run(userList.length, []);
    console.log('result',res)
  getResult()

把异步操作抽取出去,包一层promise,然后写需要的操作代码,最后resolve返回

function asyncFunc (tempArr, i) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      // 需要处理的操作,例如:
      tempArr.push(i)
      // 在异步中将结果返回
      resolve()
    }, 1)
function Func () {
  let tempArr = []
  for (let i = 0; i < 10; i++) {
    if (i % 2 == 0) {
      tempArr.push(i + 10)
    } else {
      //  setTimeout 模拟遇到的异步操作
      setTimeout(() => {
        tempArr.push(i)
      }, 1)
  console.log(56, tempArr)
}Func()
async function Func () {
  let tempArr = []
  for (let i = 0; i < 10; i++) {
    if (i % 2 == 0) {
      tempArr.push(i + 10)
    } else {
      await this.asyncFunc(tempArr, i)
  console.log(56, tempArr)
function asyncFunc (tempArr, i) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      tempArr.push(i)
      // 在异步中将结果返回
      resolve()
    }, 1)

上面的例子

function ajax(length) {
    let data = [{ name: '小明', age: 22 }, { name: '小红', age: 18 }]
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        let newData = data.map(item=>item.age*length )
        resolve(newData)
      }, 200)
 let arr = []
 for(let i= 0;i< userList.length;i++ ){ 
     console.log('before',i)
     let newData = await ajax(i+1) 
     arr.push(newData);
     console.log('after',i,newData)