Promise.all()
概念
Promise.all()方法将多个promise实例合成一个新的promise实例处理异步操作
all()方法参数是一个数组,里面存放promise实例
const p1 = new Promise(()=>{})
const p2 = new Promise(()=>{})
const p3 = new Promise(()=>{})
const p = Promise.all([p1,p2,p3]).then((res)=>{
console.log(res)
}).catch(err=>console.log(err))
元素如果不是promise实例,比如是数字,字符串或者其他类型,会自动调用 Promise.resolve()转为promise实例
const p = Promise.all([1,2,3])
//数组元素 1 ,2 ,3 会被调用 Promise.resolve() 转为promise实例
const p1 = Promise.resolve(1)
const p2 = Promise.resolve(2)
const p3 = Promise.resolve(3)
//内部会演变为这样
const p = Promise.all([p1,p2,p3])
Promise.all()的状态依据数组里的promise实例来变化
多个实例的状态都变为fulfilled的时候,Promise.all()的状态才会变为fulfilled
如果有一个实例的状态变为rejected,Promise.all()的状态会变为rejected,第一个rejected状态的实例的返回值,会传递出来到Promise.all()的then()或者catch()回调函数上来。
const getDatas = (param) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({id: param})
}, 1000)
})
}
const promises = [1, 3, 4].map(id => getDatas(id))
Promise.all(promises).then((res) => {
console.log(res)
}).catch(err => {
console.log(err)
})
三个元素promise实例状态都变为fulfilled,或者有一个状态变为rejected,才会调用all()后面的回调函数。
Promise.all()可以确定所有请求都成功了,但是只要有一个请求失败,它就会报错,而不管另外的请求是否结束。
const p1 = new Promise((resolve, reject)=>{
resolve(123)
})
const p2 = new Promise((resolve, reject)=>{
reject(234)
})
const p3 = new Promise((resolve, reject)=>{
throw new Error('error')
})
Promise.all([p1,p2,p3]).then((results)=>{
console.log(results)
}).catch(err=>console.log(err))
//234
const p1 = new Promise((resolve, reject)=>{
resolve(123)
})
const p2 = new Promise((resolve, reject)=>{
resolve(234)
})
const p3 = new Promise((resolve, reject)=>{
resolve(4556)
})
Promise.all([p1,p2,p3]).then((results)=>{
console.log(results)
})
// [123, 234, 4556]
const urls = [url_1, url_2, url_3];
const requests = urls.map(x => fetch(x));
try {
await Promise.all(requests);
console.log('所有请求都成功。');
} catch {
console.log('至少一个请求失败,其他请求可能还没结束。');
}
业务场景案例
1)下面是一个常用的Promise.all()方法的案例,多个请求并发执行,然后集合统一返回处理。
const queryUserTop = ({...params}, config = {}) => {
return post(`/partner/app/top/get`, { ...params }, config)
}
let proMap = [1, 2, 3].map(type => queryUserTop({period: 1, type}))
Promise.all(proMap).then(res => {
let resData = res.map(res => res?.result.ranking)
setTopData(resData)
}).catch((error) => {
console.log(error)
})
2)处理一组promise的异步请求,通过一组图片的每个前缀url,依次异步请求获取图片自己的base64码然后渲染图片
//index.vue
//template
<li class="policy-img" v-for="(it,index) in imageInfos">
<img :src="it.imgUrl" alt/>
<i @click="imageInfos.splice(index,1)">×</i>
</li>
//js methods
const getAllImgB64Str = (imageInfos) => {
let promiseArr = [];
imageInfos.forEach(it => {
let _param = {imgUrl: it.imgUrl, imgId: it.imgId}
promiseArr.push(getImgB64StrApi(baseUrl, _param));
});
Promise.all(promiseArr).then(res => {
this.imageInfos = res.map(result => {
let temObj = {};
if (result.code === "0200") {
temObj.imgUrl = `data:image/png;base64,${result.data.data.imgBase64String}`;
} else {
this.showPosition("middle", result.data.message);
}
return temObj;
});
}).catch(err=>{
console.log(err)
});
}
//调用方法
getAllImgB64Str(this.imageInfos);
Promise.race()
参数是数组,元素为多个promise实例,合成一个新的promise实例
元素不是promise实例也会执行resolve方法转成实例
不同于all()方法是元素实例中有一个状态变化,race()的实例状态会跟着执行变化,最先变化的promise实例的返回值,就传递给race()的回调函数。
如果前面的请求没有相应,5秒后走默认的异常处理
const errfun = ()=>{
return new Promise((resolve, reject)=>{
setTimeout(()=>{reject(new Error('request timeout'))},5000)
})
}
const pRace = Promise.race([fetch('abc.json'),errfun()])
pRace.then()
.catch(err=>console.log(err))
Promise.allSettled()
Promise.allSettled()方法接受一个数组作为参数,数组的每个成员都是一个 Promise 对象,并返回一个新的 Promise 对象。只有等到参数数组的所有 Promise 对象都发生状态变更(不管是fulfilled还是rejected),返回的 Promise 对象才会发生状态变更。
const p1 = new Promise((resolve, reject)=>{
resolve(123)
})
const p2 = new Promise((resolve, reject)=>{
reject(234)
})
const p3 = new Promise((resolve, reject)=>{
throw new Error('error')
})
Promise.allSettled([p1,p2,p3]).then((results)=>{
console.log(results)
})
这个方法也是返回promise实例对象,数组内全部promise对象状态变化后,then回调函数接收返回结果,是一个数组里面映射每个成员的变化状态和结果
// 异步操作成功时
{status: 'fulfilled', value: value}
// 异步操作失败时
{status: 'rejected', reason: reason}
如果有一个promise成员状态没有变化
const p1 = new Promise((resolve, reject)=>{
resolve(123)
})
const p2 = new Promise((resolve, reject)=>{
reject(234)
})
const p3 = new Promise((resolve, reject)=>{
})
Promise.allSettled([p1,p2,p3]).then((results)=>{
console.log(results)
})
该方法的返回状态一直处于pending,其他结果也不会返回到then方法里面
Promise.resolve()
将现有对象转成promise对象
参数是一个promise实例
const p = new Promise((resolve, reject)=>{})
Promise.resolve(p)
const p = new Promise((resolve, reject)=>{resolve()})
Promise.resolve(p)
const p = new Promise((resolve, reject)=>{reject()})
Promise.resolve(p)
Promise.resolve 不做任何修改,原封返回实例
不带任何参数
Promise.resolve()方法允许调用时不带参数,直接返回一个resolved状态的 Promise 对象。
const p = Promise.resolve();
p.then(function () {
// ...
});
需要注意的是,立即resolve()的 Promise 对象,是在本轮“事件循环”(event loop)的结束时执行,而不是在下一轮“事件循环”的开始时。
setTimeout(function () {
console.log('three');
}, 0);
Promise.resolve().then(function () {
console.log('two');
});
console.log('one');
// one
// two
// three
参数是原始值,普通对象
返回一个新的promise对象,状态为fulfilled
const p = Promise.resolve('Hello');
p.then(function (s) {
console.log(s)
});
// Hello