前提:在一个项目中经常会有一个页面同时请求多个接口的时候,但是对于用惯了async/await的人来说对于这种情况就有点问题了,一般会对这部分单独用promise.all(),这是大部分的做法,今天来讲下如何用async/await写出promise.all()效果。
1.promise.all()的请求过程(当同时并发多个接口时,会同时请求这些接口)
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => { resolve([1]) }, 1000);
})
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => { resolve([2]) }, 3000);
})
console.time(); // 开始计时
Promise.all([promise1, promise2]).then(result => {
console.timeEnd(); // 计时结束 3006.274169921875 ms
console.log(result); // (2) [Array(1), Array(1)]
})
这里有个补充,promise.all()在请求多个接口时,当有一个出现了请求失败,就不会进入到result()方法里,为了解决这个问题,ECMAScript2020 引入了 Promise.allSettled() 方法,该方法用来确定一组异步操作是否都结束了(不管成功或失败),都会返回对应的请求结果。
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => { resolve([1]) }, 1000);
})
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => { reject([2]) }, 3000);
})
console.time(); // 开始计时
Promise.all([promise1, promise2]).then(result => {
//进不来
console.timeEnd();
console.log(result,'result');
}).catch(error=>{
console.log(error,'error') //[2],error
})
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => { resolve([1]) }, 1000);
})
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => { reject([2]) }, 3000);
})
console.time(); // 开始计时
Promise.allSettled([promise1, promise2]).then(result => {
console.timeEnd(); // 计时结束 3006.274169921875 ms
console.log(result);
//{status: 'fulfilled', value: Array(1)}
//{status: 'rejected', reason: Array(1)}
})
同样是用了Promise.allSettled()会返回成功的结果
2.async/await在执行并发请求时,因为async/await是同步请求,所以在多个并发请求时会依次单个请求接口,会导致并发请求时间会叠加,增加请求时间
const promise1 = ()=>{
return new Promise((resolve, reject) => {
setTimeout(() => { resolve([1]) }, 3000);
})
}
const promise2 = ()=>{
return new Promise((resolve, reject) => {
setTimeout(() => { resolve([2]) }, 3000);
})
}
console.time(); // 开始计时
const anyPromise = async()=>{
const data1 = await promise1()
const data2 = await promise2()
console.timeEnd(); // 6027.822998046875 ms
console.log(data1,data2); //[1],[2]
}
anyPromise()
因为是同步操作,所以请求时间是累加的,改造后的用法,
const promise1 = ()=>{
return new Promise((resolve, reject) => {
setTimeout(() => { resolve([1]) }, 3000);
})
}
const promise2 = ()=>{
return new Promise((resolve, reject) => {
setTimeout(() => { resolve([2]) }, 3000);
})
}
console.time(); // 开始计时
const anyPromise = async()=>{
let a1 = promise1()
let a2 = promise2()
let data1 = await a1
let data2 = await a2
console.timeEnd(); // 3006.748046875 ms
console.log(data1,data2); //[1],[2]
}
anyPromise()
这样async/await同步的写法就可以请求并发请求了,也可以保证代码的可读性。
当然这个原生写法的实例,但如果当前项目安装使用了第三方库如axios的话,还是建议用axios来处理,毕竟作为专业级处理请求库,很多处理上还是用了很大功夫的,如axios.all、axios.spread的使用。
let promise1 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve([1]);
}, 3000);
});
};
let promise2 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve([2]);
}, 3000);
});
};
console.time();
axios.all([promise1(), promise2()]).then(
this.$axios.spread((res1, res2) => {
console.timeEnd(); //spread
console.log([1],[2]);
})
);