一起养成写作习惯!这是我参与「掘金日新计划 · 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)