【Promise】自定义promise
文章目录
- 1 定义整体结构
- 2 Promise 构造函数的实现
- 3 promise.then()与promise.catch()的实现
- 4 Promise.resolve()与Promise.reject()的实现
- 5 Promise.all与Promise.race()的实现
- 6 Promise.resolveDelay()与Promise.rejectDelay()的实现
1 定义整体结构
/*自定义 Promise
*/
(function (window) {
/*
Promise 构造函数
excutor: 内部同步执行的函数 (resolve, reject) => {}
*/
function Promise(excutor) {
}/*为 promise 指定成功/失败的回调函数
函数的返回值是一个新的 promise 对象
*/
Promise.prototype.then = function (onResolved, onRejected) {
}/*为 promise 指定失败的回调函数
是 then(null, onRejected)的语法糖
*/
Promise.prototype.catch = function (onRejected) {
}/*返回一个指定了成功 value 的 promise 对象
*/
Promise.resolve = function (value) {
}/*返回一个指定了失败 reason 的 promise 对象
*/
Promise.reject = function (reason) {
}/*返回一个 promise, 只有 promises 中所有 promise 都成功时, 才最终成功, 只要有一个失败就直接失败
*/
Promise.all = function (promises) {
}/*返回一个 promise, 一旦某个 promise 解决或拒绝, 返回的 promise 就会解决或拒绝
*/
Promise.race = function (promises) {
}// 暴露构造函数
window.Promise = Promise
})(window)
2 Promise 构造函数的实现
/*
Promise 构造函数
excutor: 内部同步执行的函数 (resolve, reject) => {}
*/
function Promise(excutor) {const self = thisself.status = 'pending' // 状态值, 初始状态为 pending, 成功了变为resolved, 失败了变为 rejectedself.data = undefined // 用来保存成功 value 或失败 reason 的属性self.callbacks = [] // 用来保存所有待调用的包含 onResolved 和 onRejected 回调函数的对象的数组/*异步处理成功后应该调用的函数value: 将交给 onResolve()的成功数据*/function resolve(value) {if(self.status!=='pending') { // 如果当前不是 pending, 直接结束return}// 立即更新状态, 保存数据self.status = 'resolved'self.data = value// 异步调用所有待处理的 onResolved 成功回调函数if (self.callbacks.length>0) {setTimeout(() => {self.callbacks.forEach(obj => {obj.onResolved(value)})})}}/*异步处理失败后应该调用的函数reason: 将交给 onRejected()的失败数据*/function reject(reason) {if(self.status!=='pending') { // 如果当前不是 pending, 直接结束return}// 立即更新状态, 保存数据self.status = 'rejected'self.data = reason// 异步调用所有待处理的 onRejected 回调函数setTimeout(() => {self.callbacks.forEach(obj => {obj.onRejected(reason)})})}try {// 立即同步调用 excutor()处理excutor(resolve, reject)} catch (error) { // 如果出了异常, 直接失败reject(error)}
}
3 promise.then()与promise.catch()的实现
/*为 promise 指定成功/失败的回调函数
函数的返回值是一个新的 promise 对象
*/
Promise.prototype.then = function (onResolved, onRejected) {const self = this// 如果 onResolved/onRejected 不是函数, 可它指定一个默认的函数onResolved = typeof onResolved==='function' ? onResolved : value => value // 指定返回的 promise 为一个成功状态, 结果值为 valueonRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason} // 指定返回的 promise 为一个失败状态, 结果值为 reason// 返回一个新的 promise 对象return new Promise((resolve, reject) => {/*专门抽取的用来处理 promise 成功/失败结果的函数callback: 成功/失败的回调函数*/function handle(callback) {// 1. 抛出异常 ===> 返回的 promise 变为 rejectedtry {const x = callback(self.data)// 2. 返回一个新的 promise ===> 得到新的 promise 的结果值作为返回的promise 的结果值if (x instanceof Promise) {x.then(resolve, reject) // 一旦 x 成功了, resolve(value), 一旦 x失败了: reject(reason)} else {// 3. 返回一个一般值(undefined) ===> 将这个值作为返回的 promise 的成功值resolve(x)}} catch (error) {reject(error)}}if (self.status === 'resolved') { // 当前 promise 已经成功了setTimeout(() => {handle(onResolved)})} else if (self.status === 'rejected') { // 当前 promise 已经失败了setTimeout(() => {handle(onRejected)})} else { // 当前 promise 还未确定 pending// 将 onResolved 和 onRejected 保存起来self.callbacks.push({onResolved(value) {handle(onResolved)},onRejected(reason) {handle(onRejected)}})}})
}
4 Promise.resolve()与Promise.reject()的实现
/*返回一个指定了成功 value 的 promise 对象
value: 一般数据或 promise
*/
Promise.resolve = function (value) {return new Promise((resolve, reject) => {if (value instanceof Promise) {value.then(resolve, reject)} else {resolve(value)}})
}/*
返回一个指定了失败 reason 的 promise 对象
reason: 一般数据/error
*/
Promise.reject = function (reason) {return new Promise((resolve, reject) => {reject(reason)})
}
5 Promise.all与Promise.race()的实现
/*返回一个新的 promise 对象, 只有 promises 中所有 promise 都产生成功 value 时, 才最
终成功, 只要有一个失败就直接失败
*/
Promise.all = function (promises) {// 返回一个新的 promisereturn new Promise((resolve, reject) => {// 已成功的数量let resolvedCount = 0// 待处理的 promises 数组的长度const promisesLength = promises.length// 准备一个保存成功值的数组const values = new Array(promisesLength)// 遍历每个待处理的 promisefor (let i = 0; i < promisesLength; i++) {// promises 中元素可能不是一个数组, 需要用 resolve 包装一下Promise.resolve(promises[i]).then(value => {// 成功当前 promise 成功的值到对应的下标values[i] = value// 成功的数量加 1resolvedCount++// 一旦全部成功if(resolvedCount===promisesLength) {// 将所有成功值的数组作为返回 promise 对象的成功结果值resolve(values)}},reason => {// 一旦有一个promise产生了失败结果值, 将其作为返回promise对象的失败结果值reject(reason)})}})
}/*返回一个 promise,一旦某个 promise 解决或拒绝, 返回的 promise 就会解决或拒绝。
*/
Promise.race = function (promises) {// 返回新的 promise 对象return new Promise((resolve, reject) => {// 遍历所有 promisefor (var i = 0; i < promises.length; i++) {Promise.resolve(promises[i]).then((value) => { // 只要有一个成功了, 返回的 promise 就成功了resolve(value)},(reason) => { // 只要有一个失败了, 返回的结果就失败了reject(reason)})}})
}
6 Promise.resolveDelay()与Promise.rejectDelay()的实现
/*返回一个延迟指定时间才确定结果的 promise 对象
*/
Promise.resolveDelay = function (value, time) {return new Promise((resolve, reject) => {setTimeout(() => {if (value instanceof Promise) { // 如果 value 是一个 promise, 取这个promise 的结果值作为返回的 promise 的结果值value.then(resolve, reject) // 如果 value 成功, 调用resolve(val), 如果 value 失败了, 调用 reject(reason)} else {resolve(value)}}, time);})
}/*返回一个延迟指定时间才失败的 Promise 对象
*/
Promise.rejectDelay = function (reason, time) {return new Promise((resolve, reject) => {setTimeout(() => {reject(reason)}, time)})
}
相关文章:
【Promise】自定义promise
文章目录 1 定义整体结构2 Promise 构造函数的实现3 promise.then()与promise.catch()的实现4 Promise.resolve()与Promise.reject()的实现5 Promise.all与Promise.race()的实现6 Promise.resolveDelay()与Promise.rejectDelay()的实现 1 定义整体结构 /*自定义 Promise */ (f…...
Docker容器部署Windows系统教程
本章教程,使用Docker容器部署一个Windows操作系统容器。 一、拉取容器 dockurr/windows:latest二、运行容器 docker run -dit --name win11 -v $PWD:/share -v /opt/iso/win11.iso:/custom.iso -p 3389:3389 -p 8006:8006 --device=/dev/kvm --cap-add NET_ADMIN --stop-tim…...
js id数组转字符串
在 JavaScript 中,将数组转换为字符串有几种常见的方法。每种方法都有其特定的用途和格式。以下是一些常用的方法: 1. Array.prototype.join(separator) join 方法将数组的所有元素连接成一个字符串,并使用指定的分隔符(默认为逗…...
如何在 Android 上增加 SELinux 权限
SELinux(Security-Enhanced Linux)是一种强制访问控制(MAC)机制,它为 Android 系统提供了额外的安全层。通过 SELinux,系统管理员可以定义细粒度的安全策略,限制进程对文件、网络和其他资源的访…...
MySQL:数据类型建表
问题:我想建一个名为create和database的库可以吗? 如果按照一般的类型来建带有关键字的库 就会出现报错 如果我们这样写的话:关键词 ,则会建库成功。 选择要进行操作的数据库 use数据库 判断选择的库是否成功 删除数据库 drop…...
Linux:版本控制器git的简单使用+gdb/cgdb调试器的使用
一,版本控制器git 1.1概念 为了能够更方便我们管理不同版本的文件,便有了版本控制器。所谓的版本控制器,就是能让你 了解到⼀个文件的历史,以及它的发展过程的系统。通俗的讲就是⼀个可以记录工程的每⼀次改动和版本迭代的⼀个…...
【React.js】AntDesignPro左侧菜单栏栏目名称不显示的解决方案
作者:CSDN-PleaSure乐事 欢迎大家阅读我的博客 希望大家喜欢 使用环境:WebStorm 目录 问题概述 原因 解决方案 解决方法 潜在问题修改 最终效果呈现 额外内容 管理员界面路由配置 WebStorm背景更换 法一: 法二: 问题概…...
力扣力扣力:91.解码方法
91. 解码方法 - 力扣(LeetCode) 在完成动态规划入门之后,我们先整一个中档题,也是前面简单题的变体。 分析思路: 在拿到最终结果之前,我们应该明确什么样的数字序列能够解码。 规则1:由于只有…...
一些面试题总结(二)
21、TCP的四次挥手? 在断开TCP连接时,需要通过四次挥手来断开,过程是: (1)客户端向服务端发送FIN1和序列号SEQx的数据包,用来关闭客户端到服务端的数据传送。然后客户端进入 FIN-WAIT-1 状态。 (2)服务端接收FIN后,…...
Hive-testbench套件使用文档
Hive-testbench套件使用文档 hive-testbench 是hortonworks的一个开源项目,用于测试和基准测试 Apache Hive 的工具集。它提供了一系列的测试数据集和查询样例,用于评估和比较 Hive 在不同配置和环境下的性能。hive-testbench 的主要目标是模拟真实的大规模数据集和复杂查询…...
大数据新视界 -- 大数据大厂之 Impala 性能优化:新技术融合的无限可能(下)(12/30)
💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…...
Python | Leetcode Python题解之第540题有序数组中的单一元素
题目: 题解: class Solution:def singleNonDuplicate(self, nums: List[int]) -> int:low, high 0, len(nums) - 1while low < high:mid (low high) // 2mid - mid & 1if nums[mid] nums[mid 1]:low mid 2else:high midreturn nums[l…...
AHB Matrix 四星级 验证笔记(2.4) Tt3.3AHB总线协议测试时的 并行数据
文章目录 前言一、代码二、错误1.地址范围2. 并行执行线程中变量覆盖的情况3.有关incr的beat 前言 来源路科验证本节搞定 T3.3 AHB总线协议的覆盖:AHB_PROTOCOL_COVER 即测试ahb slave接口和master接口支持(尽可能)全部的ahb协议传输场景&am…...
前端零基础学习Day-Eight
CSS字体和文本样式 CSS文字样式 字体:font-family 语法:font-family:[字体1][,字体2][,...] p{font-family:"微软雅黑","宋体","黑体";} 含空格字体名和中文,用英文引号括起 属性值:具体字体名&…...
贪心算法day3(最长递增序列问题)
目录 1.最长递增三元子序列 2.最长连续递增序列 1.最长递增三元子序列 题目链接:. - 力扣(LeetCode) 思路:我们只需要设置两个数进行比较就好。设a为nums[0],b 为一个无穷大的数,只要有比a小的数字就赋值…...
【论文复现】MSA+抑郁症模型总结(三)
📝个人主页🌹:Eternity._ 🌹🌹期待您的关注 🌹🌹 ❀MSA抑郁症模型 热门研究领域:情感计算的横向发展1. 概述2. 论文地址3. 研究背景4. 主要贡献5. 模型结构和代码6. 数据集介绍7. 性…...
【软件测试】敏捷模型(Scrum模型)和V模型、W模型
敏捷模型 前面的那些模型以前非常流行,但现在开发人员在使用的时候会遇到各种问题。主要困难包括在项目开发期间处理来自客户的变更请求,以及合并这些变更所需要的高成本和时间。 在实际工作中,一款产品的功能是不断在变化的 所以为了克服这…...
【go从零单排】接口(interface)和多态(Polymorphism)
🌈Don’t worry , just coding! 内耗与overthinking只会削弱你的精力,虚度你的光阴,每天迈出一小步,回头时发现已经走了很远。 📗概念 在Go语言中,interface 是一种重要的类型,用于定义一组方法…...
SI5319C-C-GM,SiliconLabs芯科 SI5319C-C-GMR,时钟合成器/抖动清除器 封装 QFN-36 在售 20000PCS 23+
SI5319C-C-GM是SiliconLabs公司生产的时钟合成器和抖动清除器。它是一款高性能的时钟解决方案,可用于各种应用领域,包括通信、数据中心、消费电子等。 该器件采用了SiliconLabs独有的DSPLL技术,能够提供低抖动和高精度的时钟信号。它具有多个…...
使用批处理脚本批量删除Maven无效依赖
背景 在开发过程中,我们经常会遇到以下情况: 在pom.xml文件中错误地指定了依赖的名称。因为网络问题,某些依赖下载不完全。依赖版本号错误,导致下载的文件无法使用。 这些情况会导致Maven在本地仓库中留下一些无效的文件&#…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...
Golang——9、反射和文件操作
反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一:使用Read()读取文件2.3、方式二:bufio读取文件2.4、方式三:os.ReadFile读取2.5、写…...
ZYNQ学习记录FPGA(一)ZYNQ简介
一、知识准备 1.一些术语,缩写和概念: 1)ZYNQ全称:ZYNQ7000 All Pgrammable SoC 2)SoC:system on chips(片上系统),对比集成电路的SoB(system on board) 3)ARM:处理器…...
基于Python的气象数据分析及可视化研究
目录 一.🦁前言二.🦁开源代码与组件使用情况说明三.🦁核心功能1. ✅算法设计2. ✅PyEcharts库3. ✅Flask框架4. ✅爬虫5. ✅部署项目 四.🦁演示效果1. 管理员模块1.1 用户管理 2. 用户模块2.1 登录系统2.2 查看实时数据2.3 查看天…...
Flask+LayUI开发手记(八):通用封面缩略图上传实现
前一节做了头像上传的程序,应该说,这个程序编写和操作都相当繁琐,实际上,头像这种缩略图在很多功能中都会用到,屏幕界面有限,绝不会给那么大空间摆开那么大一个界面,更可能的处理,就…...
