从零实现 promise 的 class 和 function 版本

Class 版

class mPromise {// 构造器constructor(executor) {// 添加属性this.PromiseState = "pending";this.PromiseResult = null;this.callbacks = [];const _this = this;function resolve(data) {if (_this.PromiseState !== "pending") return;_this.PromiseState = "fulfilled";_this.PromiseResult = data;// 执行 then onResolved 回调函数setTimeout(() => {_this.callbacks.forEach((item) => {item.onResolved(data);});});}function reject(data) {if (_this.PromiseState !== "pending") return;_this.PromiseState = "rejected";_this.PromiseResult = data;// 执行 then onRejected 回调函数setTimeout(() => {_this.callbacks.forEach((item) => {item.onRejected(data);});});}try {executor(resolve, reject);} catch (e) {reject(e);}}// then 方法then(onResolved, onRejected) {const _this = this;// 判断回调函数数组中是否是正确的回调函数// 用于实现 catch 的异常穿透,添加默认的 onRejected 回调函数if (typeof onRejected !== "function") {// 如果不是函数,就创建一个函数,抛出异常onRejected = (err) => {throw err;};}// then 没有指定 onResolved 回调函数,添加默认的 onResolved 回调函数if (typeof onResolved !== "function") {onResolved = (val) => val;}return new mPromise((resolve, reject) => {// 封装回调函数function callback(onResult) {try {const result = onResult(_this.PromiseResult);if (result instanceof mPromise) {result.then((val) => {resolve(val);},(err) => {reject(err);});} else {resolve(result);}} catch (e) {reject(e);}}// 调用回调函数if (this.PromiseState === "fulfilled") {setTimeout(() => {callback(onResolved);});}if (this.PromiseState === "rejected") {setTimeout(() => {callback(onRejected);});}if (this.PromiseState === "pending") {// 保存回调函数// 使用数组保存是为了解决多次调用then方法的问题this.callbacks.push({onResolved: () => {callback(onResolved);},onRejected: () => {callback(onRejected);},});}});}// catch 方法catch(onRejected) {return this.then(undefined, onRejected);}// resolve 方法, 是对象方法,不属于实例对象方法static resolve(value) {return new mPromise((resolve, reject) => {if (value instanceof mPromise) {value.then((val) => {resolve(val);},(err) => {reject(err);});} else {resolve(value);}});}// reject 方法, 是对象方法,不属于实例对象方法static reject(err) {return new mPromise((resolve, reject) => {reject(err);});}// all 方法static all(promises) {return new mPromise((resolve, reject) => {let count = 0;const arr = [];promises.forEach((promise, i) => {promise.then((val) => {arr[i] = val;count++;if (count === promises.length) {resolve(arr);}},(err) => {reject(err);});});});}// race 方法static race(promises) {return new mPromise((resolve, reject) => {promises.forEach((promise) => {promise.then((val) => {resolve(val);},(err) => {reject(err);});});});}
}

function 版

// 声明构造函数
function mPromise(executor) {// 添加属性this.PromiseState = "pending";this.PromiseResult = null;this.callbacks = [];const _this = this;function resolve(data) {if (_this.PromiseState !== "pending") return;_this.PromiseState = "fulfilled";_this.PromiseResult = data;// 执行 then onResolved 回调函数setTimeout(() => {_this.callbacks.forEach((item) => {item.onResolved(data);});});}function reject(data) {if (_this.PromiseState !== "pending") return;_this.PromiseState = "rejected";_this.PromiseResult = data;// 执行 then onRejected 回调函数setTimeout(() => {_this.callbacks.forEach((item) => {item.onRejected(data);});});}try {executor(resolve, reject);} catch (e) {reject(e);}
}mPromise.prototype.then = function (onResolved, onRejected) {const _this = this;// 判断回调函数数组中是否是正确的回调函数// 用于实现 catch 的异常穿透,添加默认的 onRejected 回调函数if (typeof onRejected !== "function") {// 如果不是函数,就创建一个函数,抛出异常onRejected = (err) => {throw err;};}// then 没有指定 onResolved 回调函数,添加默认的 onResolved 回调函数if (typeof onResolved !== "function") {onResolved = (val) => val;}return new mPromise((resolve, reject) => {// 封装回调函数function callback(onResult) {try {const result = onResult(_this.PromiseResult);if (result instanceof mPromise) {result.then((val) => {resolve(val);},(err) => {reject(err);});} else {resolve(result);}} catch (e) {reject(e);}}// 调用回调函数if (this.PromiseState === "fulfilled") {setTimeout(() => {callback(onResolved);});}if (this.PromiseState === "rejected") {setTimeout(() => {callback(onRejected);});}if (this.PromiseState === "pending") {// 保存回调函数// 使用数组保存是为了解决多次调用then方法的问题this.callbacks.push({onResolved: () => {callback(onResolved);},onRejected: () => {callback(onRejected);},});}});
};mPromise.prototype.catch = function (onRejected) {return this.then(undefined, onRejected);
};// 注意:这里是函数对象方法,不是实例对象方法
mPromise.resolve = function (value) {return new mPromise((resolve, reject) => {if (value instanceof mPromise) {value.then((val) => {resolve(val);},(err) => {reject(err);});} else {resolve(value);}});
};mPromise.reject = function (err) {return new mPromise((resolve, reject) => {reject(err);});
};mPromise.all = function (promises) {return new mPromise((resolve, reject) => {let count = 0;const arr = [];promises.forEach((promise, i) => {promise.then((val) => {arr[i] = val;count++;if (count === promises.length) {resolve(arr);}},(err) => {reject(err);});});});
};mPromise.race = function (promises) {return new mPromise((resolve, reject) => {promises.forEach((promise) => {promise.then((val) => {resolve(val);},(err) => {reject(err);});});});
};

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

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

相关文章

百度资源搜索平台出现:You do not have the proper credential to access this page.怎么办?

Forbidden site not allowed You do not have the proper credential to access this page. If you think this is a server error, please contact the webmaster. 如果你的百度资源平台,点进去出现这个提示,说明您的网站已经被百度清退了。如果你的网站…

Java循环对比:传统for循环、增强型for循环和forEach循环

1、传统for循环 传统的for循环是一种经典的循环结构,在Java中广泛使用。 以下是传统for循环的特点: 灵活控制:传统for循环使用形式为for (初始化表达式; 终止条件; 步进表达式)的语法,可以手动控制循环的索引,并根据需…

C语言数组和指针笔试题(三)(一定要看)

目录 字符数组四例题1例题2例题3例题4例题5例题6例题7 结果字符数组五例题1例题2例题3例题4例题5例题6例题7结果字符数组六例题1例题2例题3例题4例题5例题6例题7 结果 感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接 🐒🐒🐒个…

【数值计算方法】非线性方程(组)和最优化问题的计算方法:非线性方程式求根的二分法、迭代法、Newton 迭代法及其Python实现

目录 一、非线性方程式求根 1、二分法(Bisection Method、对分法) a. 理论简介 b. python实现 2、迭代法(Iterative Method) a. 理论简介 b. python实现 3、Newton 迭代法(Newtons Method) a. 理论…

电脑入门:电脑不认新硬盘时该怎么办?

电脑不认新硬盘时该怎么办? 当新硬盘加进后,正常工作时,没有什么问题。若电脑遇到特殊情况时,电脑对新硬盘“不认”,可采取以下措施让电脑重新“认”新硬盘,显示新分区(如G、H、I、J)。 咱的目的是保持S-ATA的开启,把控制板载S-ATA设定值由No变成Yes就可以。 首…

【数据结构与算法】链表的实现以及一些基本算法

目录 单选链表的基本实现 有序列表的合并(双指针法) 链表的反转 链表实现两数之和 判定链表是否有环 单选链表的基本实现 public class LinkedList1 {//头节点Node first;//尾节点Node last;//大小int size 0;//头插法public void addFirst(int…

微信小程序学习笔记3.0

第3章 资讯类:仿今日头条微信小程序 3.1 需求描述及交互分析 需求描述 仿今日头条微信小程序,要具有以下功能。 (1)首页新闻频道框架设计,包括底部标签导航设计、新闻检索框设计及新闻频道滑动效果设计。 (2)首页新闻内容设计,包括新闻标题、新闻图片及新闻评论设计…

springcloudgateway 默认转发不生效

配置文件配置了自动转发 spring.cloud.gateway.discovery.locator.enabled true 但是用微服务路径访问时一直报503 [fa9cc893-1] There was an unexpected error (typeService Unavailable, status503). 这个503看得我是一头雾水。原因在于这个默认错误页的报错显示不全…

TikTok的媒体革命:新闻业如何适应短视频时代?

在数字时代,媒体行业一直在不断演变和创新,以适应观众的变化需求和技术的发展。而在这个进化的过程中,短视频应用TikTok已经崭露头角,成为了一个重要的信息传播平台。 这篇文章将深入探讨TikTok如何引领了媒体的一场革命&#xf…

转载-C#学习笔记-基本概念(CLR、CTS、CLS...)

1. CLR(Common Language Runtime,公共语言运行时(库)) 可由多种.NET语言使用的运行时环境,其主要作用是定位、加载和管理.NET类型、内存管理、安全检查、线程管理等。.NET运行库提供了一个定义明确的运行库层,可以被支持.NET的所有语言和平台…

2、Linux中静态IP与动态IP的修改

修改为静态IP 打开文件 sudo vim /etc/network/interfaces修改如下 # interfaces(5) file used by ifup(8) and ifdown(8) auto lo iface lo inet loopbackauto ens33#配置网络为DHCP模式 #iface ens33 inet dhcp#配置网络 ens33为静态IP模式 iface ens33 inet static #设置…

基于Vue+ELement搭建动态树与数据表格实现分页

基于VueELement搭建动态树与数据表格实现分页 一、前言二、左侧动态树实现2.1.后台数据接口定义2.2.前端导航菜单绑定2.3.根据数据渲染页面 3.分页 一、前言 在上一篇博文我们搭建了首页导航和左侧菜单,但是我们的左侧菜单是死数据今天我们就来把死的变成活的&#…

自学WEB后端01-安装Express+Node.js框架完成Hello World!

一、前言,网站开发扫盲知识 1.网站搭建开发包括什么? 前端 前端开发主要涉及用户界面(UI)和用户体验(UX),负责实现网站的外观和交互逻辑。前端开发使用HTML、CSS和JavaScript等技术来构建网页…

jquery相关操作--但是高级有些不太明白

jquery介绍 jQuery是目前使用最广泛的javascript函数库。据统计,全世界排名前100万的网站,有46%使用jQuery,远远超过其他库。微软公司甚至把jQuery作为他们的官方库。 jQuery的版本分为1.x系列和2.x、3.x系列,1.x系列兼容低版本…

Leetcode 386. 字典序排数

文章目录 题目代码&#xff08;9.22 首刷看解析&#xff09; 题目 Leetcode 386. 字典序排数 代码&#xff08;9.22 首刷看解析&#xff09; 迭代DFS class Solution { public:vector<int> lexicalOrder(int n) {vector<int> ret(n);int number 1;for(int i 0…

目标检测YOLO实战应用案例100讲-面向路边停车场景的目标检测(中)

目录 3.1.1 特征图相似度计算 3.1.2 特征图相似度实验 3.1.3 基于GhostBlock的网络结构改进

SVN -基础

SVN - 基础 概念操作步骤开发实际经验 概念 带SVN路径 有隐藏文件&#xff0c;记录repo的一些信息&#xff0c;与repo进行关联&#xff0c;可以与repo进行同步 不带SVN路径 只是单纯的文件&#xff0c;与repo独立 操作步骤 checkout 具有路径 URLcheckout dir 输出目标文件夹…

Flink--6、输出算子(连接到外部系统、文件、kafka、MySQL、自定义Sink)

星光下的赶路人star的个人主页 世间真正温煦的春色&#xff0c;都熨帖着大地&#xff0c;潜伏在深谷 文章目录 1、输出算子&#xff08;Sink&#xff09;1.1 连接到外部系统1.2 输出到文件1.3 输出到Kafka1.4 输出到MySQL&#xff08;JDBC&#xff09;1.4 自定义Sink输出 1、输…

【数学建模】2023华为杯研究生数学建模F题思路详解

强对流降水临近预报 我国地域辽阔&#xff0c;自然条件复杂&#xff0c;因此灾害性天气种类繁多&#xff0c;地区差异大。其中&#xff0c;雷雨大风、冰雹、龙卷、短时强降水等强对流天气是造成经济损失、危害生命安全最严重的一类灾害性天气[1]。以2022年为例&#xff0c;我国…

我的python安装在哪儿了?python安装路径怎么查?

对于 Python 开发者来说&#xff0c;Windows 系统中的 Python 安装路径是非常重要的。在本文中&#xff0c;我们将从多个方面探究如何查看 Python 安装路径&#xff0c;并提供代码示例。 一、使用文件浏览器查看 Python 安装路径 在 Windows 系统中&#xff0c;我们可以使用文…