首个成功的Promise

从一组Promise里面得到第一个“成功的”结果,同时获得了并发执行的速度和容灾的能力。

Promise.race不满足需求,因为如果有一个Promise reject,结果Promise也会立即reject。
function firstSuccess(promises){  return Promise.all(promises.map(p => {    // If a request fails, count that as a resolution so it will keep    // waiting for other possible successes. If a request succeeds,    // treat it as a rejection so Promise.all immediately bails out.    return p.then(      val => Promise.reject(val),      err => Promise.resolve(err)    );  })).then(    // If '.all' resolved, we've just got an array of errors.    errors => Promise.reject(errors),    // If '.all' rejected, we've got the result we wanted.    val => Promise.resolve(val)  );}

这个方法适合的场景:

  • 有多条路可以走,其中任意一条路走通即可,其中有一些路失败也没关系
  • 为了加速得到结果,并发地走多条路,避免瀑布式尝试

参考自 https://stackoverflow.com/a/3...

异步reduce

通过瀑布式的异步操作,将一个array reduce成一个值。

(async () => {    const data = [1, 2, 3]    const result = await data.reduce(async (accumP, current, index) => {      // 后面的处理要等待前面完成      const accum = await accumP;      const next = await apiCall(accum, current);      return next    }, 0);    console.log(result)  // 6    async function apiCall(a, b) {        return new Promise((res)=> {            setTimeout(()=> {res(a+b);}, 300)        })    }})()
对reduce的运用堪称巧妙!

与更常见的【array.map + Promise.all方案】对比:

(async () => {  const data = [1, 2, 3]  const result = await Promise.all(    data.map(async (current, index) => {      // 处理是并发的      return apiCall(current)    })  )  console.log(result)  async function apiCall(a) {    return new Promise((res) => {      setTimeout(() => {        res(a * 2)      }, 300)    })  }})()
  • 两个方案相同点:对每个数组项执行处理,并且其中任一次处理的失败都会造成整体失败
  • reduce方案是瀑布式的,map方案是并发的

参考自 https://stackoverflow.com/a/4...