写点什么

【Promise 源码学习】第十三篇 - Promise.allsettled 和 Promise.any 的实现

作者:Brave
  • 2021 年 12 月 06 日
  • 本文字数:2233 字

    阅读完需:约 7 分钟

一,前言


上一篇,主要实现了 Promise 静态 API(类方法):Promise.race,主要涉及以下几个点:


  • 测试原生 Promise.race 的使用;

  • Promise.race 的功能与特性分析;

  • Promise.race 的源码实现、执行分析、功能测试;


本篇,继续实现 Promise 静态 API:Promise.allSettledPromise.any


二,Promise.allsettled 简介

1,API 介绍

MDN 参考资料


Promise.allsettled

  • 批处理 promise,返回 promise;

  • 存在失败结果也会拿到全部执行结果,不会走 catch;

  • 解决了 Promise.all 不能拿到失败执行结果的问题;

2,原生 Promise.allsettled 功能测试


// p1:立即成功const p1 = Promise.resolve("p1_success");// p2:2 秒后成功const p2 = new Promise((resolve, reject) => setTimeout(resolve, 2000, 'p2_success'));// p3:1 秒后失败const p3 = new Promise((resolve, reject) => setTimeout(reject, 1000, 'p3_success'));
Promise.allSettled([p1, p2, p3, 1]). then((results) => results.forEach((result) => console.log(result))); // 执行结果:2 秒后全部执行完成{ status: 'fulfilled', value: 'p1_success' }{ status: 'fulfilled', value: 'p2_success' }{ status: 'rejected', reason: 'p3_success' }{ status: 'fulfilled', value: 1 }
复制代码


  • allSettled 现象:全部执行完成,返回执行结果数组(下标与按执行顺序一致)


三,Promise.allsettled 实现

原理分析


  • Promise.allsettled:入参是一个 promise 集合;返回一个 Promise 实例;Promise.allsettled 内部 return new Promise(...)

  • 所有 promise 都会被执行完,并且按照执行顺序返回执行结果;Promise.allsettled 不会走 reject,按执行顺序全部收集到数组后 resolve 返回即可;

2,代码实现


// allSettle:全部执行完成后,返回全部执行结果(成功+失败)static allSettled(promises) {  const result = new Array(promises.length); // 记录执行的结果:用于返回直接结果  let times = 0;     // 记录执行完成的次数:判断是否完成  return new Promise((resolve, reject) => {    for (let i = 0; i < promises.length; i++) {      let p = promises[i];      if (p && typeof p.then === 'function') {        p.then((data) => {          result[i] = { status: 'fulfilled', value: data }          times++;          if (times === promises.length) {            resolve(result);          }        }).catch(err => {          result[i] = { status: 'rejected', reason: err }          times++;          if (times === promises.length) {            resolve(result);          }        })      } else { // 普通值,加入        result[i] = { status: 'fulfilled', value: p }        times++;        if (times === promises.length) {          resolve(result);        }      }    }  })}
复制代码



四,Promise.any 简介

1,API 介绍

MDN 参考资料


Promise.any

  • 批处理 promise,返回 promise;

  • 返回第一个成功结果,全部失败才返回失败;

  • 解决了 Promise.race 只能拿到第一个执行完成(不管成功/失败)的结果;


五,Promise.any 实现

原理分析


  • Promise.any:入参是一个 promise 集合;返回一个 Promise 实例;Promise.any 内部 return new Promise(...)

  • 执行所有 promise,使用最先返回的成功结果;全部失败才判定为失败;p.then("谁先成功就返回谁","失败了先存起来,都失败了才返回")

2,代码实现


// any:一个成功就成功,全部失败才失败static any(promises) {  const rejectedArr = []; // 记录失败的结果  let rejectedTimes = 0;  // 记录失败的次数  return new Promise((resolve, reject) => {    if(promises == null || promises.length == 0){      reject("无效的 any");    }    for (let i = 0; i < promises.length; i++) {      let p = promises[i];      // 处理 promise      if (p && typeof p.then === 'function') {        p.then((data) => {          resolve(data) // 使用最先成功的结果        }, (err) => { // 如果失败了,保存错误信息;当全失败时,any 才失败          rejectedArr[i] = err;          rejectedTimes++;          if (rejectedTimes === promises.length) {            reject(rejectedArr);          }        })      }else{// 处理普通值,直接成功        resolve(p)      }    }  })}
复制代码

3,功能测试


const pErr = new Promise((resolve, reject) => {  setTimeout(reject, 1000, "失败了");});
const pSlow = new Promise((resolve, reject) => { setTimeout(resolve, 5000, "慢的成功");});
const pFast = new Promise((resolve, reject) => { setTimeout(resolve, 2000, "快的成功");});
Promise.any([pErr, pSlow, pFast]).then((value) => { console.log("Promise.any 成功", value);}).catch(err =>{ console.log("Promise.any 失败", err);})
// 执行结果:2 秒后返回:"Promise.any 成功 快的成功";5 秒后执行完成;
复制代码



六,结尾


本篇,主要实现 Promise 静态 API:Promise.allSettledPromise.any,主要涉及以下几个点:


  • 测试原生 Promise.allsettled 的使用;

  • Promise.allsettled 原理分析、源码实现、功能测试;

  • Promise.any 原理分析、源码实现、功能测试;


下一篇,实现一个 promisify 工具函数;

用户头像

Brave

关注

还未添加个人签名 2018.12.13 加入

还未添加个人简介

评论

发布
暂无评论
【Promise 源码学习】第十三篇 - Promise.allsettled 和 Promise.any 的实现