前言
Promise
是 es6
新出的语法,用来处理异步请求,解决之前没有 Promise
时的回调地狱。Promise
有几个api, Promise.resolve
,Promise.reject
,Promise.all
,Promise.race
。关于多个异步的处理我们可以用 Promise.all
,但 Promise.all
只在所有的 promise
都 resolve
时才会调用 .then
中的成功回调。 有时候多个请求难免会有失败的情况,我们想当 Promise.all
中的 promise
对象 reject
失败时也能够调用回调函数,这个时候应该怎么做呢?
开搞
我们先来了解下 Promise.all
的用法。
Promise.all([Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)])
.then(res => console.log(res),err=>console.log(err))
// [1, 2, 3]
Promise.all([Promise.reject(1), Promise.resolve(2), Promise.resolve(3)])
.then(res => console.log(res),err=>console.log(err))
// 1
Promise.all
中传入的是多个 promise
对象组成的数组。数组中所有的 promise
成功时才会打印 res
,只要有一个失败就会打印 err
。
我们想要达到就算失败也能打印所有的信息,应该怎么做呢?很简单,用.then
因为.then
返回的也是一个 promise
对象,不管是resolve
还是reject
都会执行.then
。返回promise
对象后就变成resovle
状态了。
Promise.all([Promise.reject(1).then((res) => ({ status: 'ok', res }), (err) => ({ status: 'not ok', err })),
Promise.resolve(2).then((res) => ({ status: 'ok', res }), (err) => ({ status: 'not ok', err })),
Promise.resolve(3).then((res) => ({ status: 'ok', res }), (err) => ({ status: 'not ok', err }))])
.then(res => console.log(res),err=>console.log(err))
//[ {status: "not ok", err: 1},{status: "ok", res: 2},{status: "ok", res: 3}]
这样就打印出了所有的信息,即便Promise.all
中有reject
状态。
优化封装
现在这种写法很繁琐,每个数组中的每个promise
都要写同样的.then
。我们可以把.then
抽离出来。封装成一个函数,然后用map
方法,对每个promise
.then
一下,然后返回新的数组。
function handlePromise(promiseList) {
return promiseList.map(promise =>
promise.then((res) => ({ status: 'ok', res }), (err) => ({ status: 'not ok', err }))
)
}
这样调用promise.all
时,可以这么写:
Promise.all(handlePromise([Promise.reject(1),Promise.resolve(2),Promise.resolve(3)]))
.then(res => console.log(res),err=>console.log(err))
也是同样的效果。
甚至我们可以写一个Promise.allSettled
方法:
Promise.allSettled2 = function (promiseList) {
return Promise.all(handlePromise(promiseList))
}
Promise.allSettled2 ([Promise.reject(1),Promise.resolve(2),Promise.resolve(3)]).then(res => console.log(res), err => console.log(err))
这就是promise
新出的allSettled
Api`,只不过兼容性不太好,不过没事,看了这篇文章之后,我们可以自己封装个一样功能的api了。完结撒花。