Promise.all 的缺陷

前言

Promisees6 新出的语法,用来处理异步请求,解决以前没有 Promise 时的回调地狱。Promise 有几个api, Promise.resolve,Promise.reject,Promise.all,Promise.race。关于多个异步的处理咱们能够用 Promise.all,但 Promise.all 只在全部的 promiseresolve 时才会调用 .then 中的成功回调。 有时候多个请求不免会有失败的状况,咱们想当 Promise.all中的 promise 对象 reject 失败时也可以调用回调函数,这个时候应该怎么作呢?es6

开搞

咱们先来了解下 Promise.all 的用法。api

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

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))
复制代码

也是一样的效果。ui

甚至咱们能够写一个Promise.allSettled方法:spa

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了。完结撒花。 code

image.png