Promise.all()
当我们想“并发执行”若干个任务的时候,比如要加载网站的首页,期望是要等api请求结束拿到数据后,才展示完整的首页,我们很容易就想到了Promise.all。
但是Promise.all有一个缺陷:当有一个任务失败的时候,就会直接进入catch的逻辑了。这个可能并不是我们想要的结果。
我们期望每一个请求都被监测到都被返回,不能因为请求接口失败而阻塞页面数据渲染。
Promise.all([]),执行规则是按异步耗时最长的Promise触发回调,回调结果也是一个数组,即Promise数组的所有结果
1、如果传入的参数是一个空的可迭代对象,那么此promise对象回调完成(resolve),只有此情况,是同步执行的,其它都是异步返回的。
2、如果传入的参数不包含任何 promise,则返回一个异步完成. promise 中所有的promise都promise都“完成”时或参数中不包含 promise 时回调完成。
3、如果参数中有一个promise失败,那么Promise.all返回的promise对象失败 在任何情况下,Promise.all 返回的 promise 的完成状态的结果都是一个数组
先看一个例子
testPromiseAll() {
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('promise1 fulfilled')
}, 1000)
})
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('promise2 rejected')
}, 2000)
})
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('promise3 fulfilled')
}, 3000)
})
return Promise.all([promise1, promise2, promise3]);
}
testPromiseAll().then(res => {
console.log(res)
}).catch(err => {
console.log(err) // 报错:promise2 被rejected了,后面的promise3被阻塞没有被输出
})
所以解决方案有:非返回是非promise,直接被resolve
async promiseAllWithError(promise) {
try {
const p = await promise;
// 非Promise,默认resolve
return {
status: 'fulfilled',
data: p
}
} catch(err) {
// 非Promise,默认resolve
return {
status: 'rejected',
data: err
}
}
}
// 上面testSolvePromiseAllWithError 修改成:
testSolvePromiseAllWithError() {
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('promise1 fulfilled')
}, 1000)
})
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('promise2 rejected')
}, 2000)
})
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('promise3 fulfilled')
}, 3000)
})
return Promise.all([promise1, promise2, promise3].map(promise => this.promiseAllWithError(promise)))
}
testPromiseAll().then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
log 如下
Promise.race()
race是赛跑
Promise.race(),执行规则是按异步耗时最端的Promise触发回调,回调结果是解析为迭代中找到的第一个值,哪个快返回哪个。
testPromiseRace() {
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('promise1 fulfilled')
}, 1000)
})
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('promise2 fulfilled')
}, 2000)
})
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('promise3 fulfilled')
}, 3000)
})
return Promise.race([promise1, promise2, promise3])
}
testPromiseRace().then(res => {
console.log('promise race result:', res) // promise1 fulfilled
}).catch(err => {
console.error('error', err)
})