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

news2024/11/19 12:36:49

一,前言

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

  • 测试原生 Promise.race 的使用;
  • Promise.race 的功能与特性分析;
  • Promise.race 的源码实现、执行分析、功能测试;

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


二,Promise.allsettled 简介

1,API 介绍

MDN 参考资料

image.png

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 实现

1,原理分析

  • 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 参考资料

image.png

Promise.any

  • 批处理 promise,返回 promise;
  • 返回第一个成功结果,全部失败才返回失败;
  • 解决了 Promise.race 只能拿到第一个执行完成(不管成功/失败)的结果;

五,Promise.any 实现

1,原理分析

  • 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 工具函数;


维护记录

  • 20211120
    • 修改结尾部分,更新文章摘要

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/191645.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

10、声明和创建字符串

目录 一、声明字符串 二、创建字符串 &#xff08;1&#xff09;String(char a[]) &#xff08;2&#xff09;String(char a[], int offset, int length) &#xff08;3&#xff09;String(char[] value) 一、声明字符串 在Java语言中字符串必须包含在一对双引号&#xf…

记录每日LeetCode 2325.解密消息 Java实现

题目描述&#xff1a; 给你字符串 key 和 message &#xff0c;分别表示一个加密密钥和一段加密消息。解密 message 的步骤如下&#xff1a; 使用 key 中 26 个英文小写字母第一次出现的顺序作为替换表中的字母 顺序 。 将替换表与普通英文字母表对齐&#xff0c;形成对照表。…

【Flink】详解StreamGraph

概述 没有看上一期的小伙伴请先看上一期【Flink】浅谈Flink架构和调度&#xff0c;上一期的一个核心内容就是 Flink 中的执行图可以分成四层&#xff1a;StreamGraph → JobGraph → ExecutionGraph → 物理执行图。 今天我们好好谈论一下StreamGraph&#xff0c;StreamGraph…

WPF MaterialDesignIn 收银系统(2)主界面

前言 接上一篇&#xff0c;既然登陆页面搞定了&#xff0c;接下来就是登陆成功后跳转的主界面了。 界面 思考 到了这一步&#xff0c;我们就要开始思考&#xff0c;怎么来丰富我们的应用&#xff0c;最少需要哪些东西、功能、模块、数据等等&#xff0c;才能支撑起一个收银系统…

java分支语句

流程控制1.1流程控制语句概述1.2流程控制语句分类顺序结构顺序结构是程序中最简单最基本的结构。分支结构(if,switch)循环结构(for,while,do...while)if语句2.1if语句格式1//格式 if(关系表达式){ 语句体&#xff1b; }执行流程&#xff1a;首先计算关系表达式的值如果关系表达…

每日一练10——井字棋密码强度等级

文章目录井字棋思路&#xff1a;代码&#xff1a;密码强度等级思路&#xff1a;代码&#xff1a;井字棋 题目链接&#xff1a; 思路&#xff1a; 井字棋&#xff0c;是一种在3*3格子上进行的连珠游戏&#xff0c;三个相同就代表获胜。 井字棋有四种情况表示当前玩家获胜&…

MySQL 面试题(一):索引失效的几种情况

❤️ 博客首页&#xff1a;水滴技术 &#x1f680; 支持水滴&#xff1a;点赞&#x1f44d; 收藏⭐ 留言&#x1f4ac; &#x1f338; 订阅专栏&#xff1a;MySQL 教程&#xff1a;从入门到精通 文章目录一、like 以通配符 % 开头的索引会失效二、is not null 无法使用索引&a…

SGI STL二级空间配置器源码剖析(1)

之前大概写过SGI STL相关的东西有关SGI STL&#xff0c;讲了讲空间配置器的原理&#xff0c;这一系列就剖析一下源码。 目录 下面就看看重要成员信息&#xff1a; 两个辅助接口函数&#xff1a; 关于C的STL的空间配置器allocator的实现就是分了四部分&#xff1a; allocate&…

云原生学习——容器的基本概念和Kubernetes 核心概念

https://developer.aliyun.com/learning/course/572/detail/7786什么是容器(Container)&#xff1f;什么是镜像(docker)&#xff1f;分层和复用运行后名称为 demo&#xff0c;进程是top命令二、容器的生命周期数据卷是一个特殊的目录四、容器 VS VM虚拟机一、什么是 Kubernetes…

KD:Distilling the Knowledge in a Neural Network 原理与代码解析

paper&#xff1a;Distilling the Knowledge in a Neural Networkcode&#xff1a;https://github.com/megvii-research/mdistiller/blob/master/configs/cifar100/kd.yaml存在的问题训练阶段&#xff0c;我们可以不考虑计算成本和训练时间&#xff0c;为了更高的精度训练一个很…

小程序提升篇-npm、数据共享、分包、自定义tabBar

npm 包的使用1.1 npm限制小程序支持npm第三方包&#xff0c;提高开发效率&#xff0c;有以下三种限制&#xff1a;不支持依赖node.js内置库包不支持依赖浏览器内置对象的包不支持依赖C插件的包限制较多&#xff0c;因此小程序可以使用的包不多1.2 Vant Weapp是一套开源的小程序…

带你读懂——频率响应与采样频率之间的关系

频响范围 频率响应&#xff1a;不同频率下的输入信号经过系统后响应之后的输出信号增益。大白话就是&#xff0c;输入信号频率是xxx Hz&#xff0c;幅值为yyy mg&#xff0c;观察此时的输出信号幅值为AyAyAy mg&#xff0c;此时升高或降低了AAA倍。 电压增益计算公式&#xff…

浅读人月神话笔记(2)

读书笔记&#xff1a;今日翻书浅读&#xff0c;从《为什么巴比伦塔会失败》开始至《干将莫邪》结束&#xff0c;巴比伦塔的建造对当下项目推进有广泛借鉴意义&#xff0c;今天这几个章节在PMBOK中有一些可以互相对照学习的内容&#xff0c;《为什么巴比伦塔会失败&#xff1f;》…

RPA自动化办公04——软件自动化(excel,word,浏览器)

参考&#xff1a;软件自动化_UiBot开发者指南 虽然我们可以使用前面的鼠标点击等操作打开excel表然后写入什么的&#xff0c;但是直接用Uibot里面的命令会更方便。 Excel 在旁边的命令里面打开excel簿 随便选一个excel表实验一下&#xff0c;然后读取区域&#xff0c;可以选。…

使用字典快速获取唯一值与重复值【单个字典对象】

在以前的博客《使用字典快速获取唯一值与重复值&#xff08;交集与并集&#xff09;》使用多个字典对象获取交集与并集&#xff0c;最近有同学提问&#xff0c;是否可以只使用一个字典对象实现相同的功能&#xff0c;对于有“编程洁癖”的同学来说&#xff0c;可能不喜欢使用多…

记录:windows+opencv3.4.16+vs2013+cmake编译

环境&#xff1a;vs2013,x64&#xff0c;opencv3.4.16&#xff0c;cmakeopencv官网&#xff1a;https://opencv.org/releases/1、opencv source下载&#xff1a;因为想用vs2013&#xff0c;现在opencv官网windows版安装包只有vc14和vc15了&#xff0c;只能自己编译了。找一个自…

良心无广的3款软件,每一款都逆天好用,且用且珍惜

闲话少说&#xff0c;直上干货&#xff01; 1、清浊 清浊是一款强大到离谱的国产手机清理APP&#xff0c;追求简约至上&#xff0c;界面非常清爽&#xff0c;无任何弹弹屏广告&#xff0c;值得关注的是&#xff0c;这款软件完全免费使用&#xff0c;常规清理、应用清理、空文件…

活体识别4:论文笔记之《Face Spoofing Detection Using Colour Texture Analysis》

说明 本文是我对论文《Face Spoofing Detection Using Colour Texture Analysis》做的一个简单笔记。 这个论文是芬兰奥卢大学(Oulu)课题组的一篇很有代表性的论文&#xff0c;写于2016年&#xff0c;使用的是“手工特征SVM分类器”这种比较传统的方案&#xff0c;方案不复杂&…

吾爱2023新年红包题第三题

吾爱论坛2023年春节红包安卓题&#xff0c;随便玩一玩&#xff1b; https://www.52pojie.cn/thread-1738015-1-1.html 第三题&#xff1a;https://www.52pojie.cn/home.php?modtask&doview&id22 首先我们下载后&#xff0c;打开apk是提示要点击 999次即可通关&…

Docker - 4. Docker 帮助启动类命令

目录 1. 启动 docker 2. 停止 docker 3. 重启 docker 4. 查看 docker 状态 5. 保持开机自动启动 6. 显示 docker 版本信息 7. 显示 docker 系统信息 8. 查看 docker 总体帮助文档 9. 查看 docker 命令帮助文档 1. 启动 docker systemctl start docker 2. 停止 dock…