Promise.all()
Promise.all()是什么? 我们先来回顾一下它的常见用例,如图:
Promise.all()可以接收多个promise实例,这些实例包裹成一个数组作为参数传递进去。 并且Promise.all(arr)返回一个promise,假设称为p1,可以进行.then。只有数组中所有的promise都resolved后,p1才会resolved并且结果值是一个数组,结果值数组的排列顺序和传进去的参数顺序一致。
Promise.all()方法接收一个promise的iterable类型。(Array、Map、Set都属于ES6的iterable类型)的属于,并且只返回一个promise实例。
function promiseAll(promises){
// Promise.all会返回一个promise
return new Promise((resolve,reject)=>{
if(!Array.isArray(promises)){
return reject(new TypeError(`arguments must be Array`))
}
let count = 0
// newValues是结果数组,最后resolve的是这个结果数组
let newValues = new Array(promises.length)
for(let i = 0; i < promises.length; i++){
Promise.resolve(promises[i]).then(res=>{
count++
newValues[i] = res
if(count == promises.length){
return resolve(newValues)
}
},
// 一旦有promise被拒绝,就立即reject
// 尽管循环可能还会继续,但是没关系,all方法的promise的状态只能改变一次
err => reject(err))
}
})
}
注意到没。遍历promises参数数组里的每个promise实例时,是裹在Promise.resolve里的。这是为什么呢?
按照我们想的,在内部我们要想拿到每个promise实例的resolved值,只需要调用该实例的.then方法就可以拿到。 像下面这样:
var newValues = new Array(promises.length)
for(let i = 0; i < promises.length; i++){
promises[i].then(res=>{
newValues[i] = res
})
}
当然,如果你的参数里放的都是promise实例,这样当然没有问题。可是,你有时候也会这样写
很明显,222 这就是个普通值,它可没有.then方法。那你要这么写岂不是报错了。所以我们就用Promise.resolve() 来裹一层。把普通值222变为已经resolved为222的promise。 [p1,222,p3] 就都变成了promise实例,都可以执行promise的.then方法(注:对于已经是promise的清空,Promise.resolve也只会返回一个一模一样的副本而已. 可以看看这篇加深理解. Promise.resolve())
用途
Promise.all 可以用在处理多个异步操作时,比如说一个页面需要等到两个或者多个ajax的数据都返回后才现实, 在此之前只显示loading图标.
Promise.race()
Promise.race接收的参数和all方法一样. 区别是,race方法只要成功了一个就立刻返回.
Promise.race([p1,p2,p3]) 谁先成功就返回谁.
Promise.race = function(promises){
if(!Array.isArray(promises)){
return reject(new TypeError(`arguments must be Array`))
}
return new Promise((resolve,reject)=>{
for(let i = 0; i < promises.length; i++){
Promise.resolve(promises[i]).then(value=>{
// 期间只要有一个promise实例resolved就直接在race的promise里 resolve,即使循环还在继续也没事,因为race的promise的状态只会改变一次
resolve(value)
},reason =>{ reject(reason) })
}
})
}
用途
race的使用场景就是, 多台服务器部署了同样的服务端代码,假如我要获取一个商品列表接口, 我可以在race中写上所有服务器中的查询列表的接口地址,哪个服务器响应快,就从哪个服务器拿数据.
参考:
all方法 手写promise_promise.all的实现
理解和使用Promise.all和Promise.race