超详细!一次性搞懂手写Promise全过程

news/2024/4/27 9:38:24/文章来源:https://blog.csdn.net/qq_41852789/article/details/128453341

一、Promise的使用

在学习如何写Promise之前,先要熟悉Promise的使用,然后一步一步去实现

【Promise的基本使用】:

1. Promise 是一个类 在执行这个类的时候需要传递一个执行器进去,执行器会立即执行

2. Promise中有三种状态,分别是:等待pending 成功fulfilled 失败rejected(状态一旦确定不可改变)

3. 执行器接收两个参数resolve(成功执行的方法)和reject(失败执行的方法)

4. Promise拥有then方法,方法内部需判断状态,接收了两个回调函数,如果成功调用成功的回调,如果失败调用失败的回调。then方法是被定义在原型对象中的

const promise = new Promise((resolve, reject) => {resolve('成功')// reject('失败')
})
promise.then(value => {console.log(value)
}, reason => {console.log(reason)
})

二、手写Promise

【实现步骤】:

  1. 创建MyPromise类
  2. 通过构造函数constructor,在执行这个类的时候需要传递一个执行器进去并立即调用
  3. 定义resolve和reject(定义为箭头函数:避免直接调用时this指向全局window问题)
  4. 定义状态常量(成功fulfilled 失败rejected 等待pending),初始化为pending。
  5. 完成resolve和reject函数的状态改变(注意:需判断当前状态是否可以改变)
  6. MyPromise类中定义value和reason,用来储存执行器执行成功和失败的返回值
  7. MyPromise类中添加then方法,成功回调有一个参数 表示成功之后的值;失败回调有一个参数 表示失败后的原因
  8. 处理异步逻辑(pending状态下在then中将回调存起来)
  9. 实现then方法多次调用添加多个处理函数
  10. 实现then方法链式调用(写一个函数方法专门判断回调的结果是普通值还是promise,then方法返回的仍然是一个promise)
  11. 处理promise返回值各种类型情况(普通值,promise)
  12. then方法链式调用识别Promise对象自返回
  13. Promise实现捕获错误及then链式调用其他状态代码补充
  14. 将then方法的参数变为可选参数
  15. Promise.all
  16. Promise.resolve 返回一个promise
  17.  finally方法 不管成功失败都会执行一次
  18. catch方法的实现

【代码】:

// 4. 定义状态常量(成功fulfilled 失败rejected 等待pending),初始化为pending。
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'// 1 创建MyPromise类 
class MyPromise {// 2 通过构造函数constructor,在执行这个类的时候需要传递一个执行器进去并立即调用constructor(executor) {// 13 Promise实现捕获错误try {executor(this.resolve, this.reject)} catch (e) {this.reject(e)}}status = PENDING//  6. MyPromise类中定义value和reason,用来储存执行器执行成功和失败的返回值value = nullreason = null// 9. 实现then方法多次调用添加多个处理函数 初始化回调为数组依次执行successCallback = []failCallback = []// 3. 定义resolve和reject(定义为箭头函数:避免直接调用时this指向全局window问题)resolve = value => {// 5. 完成resolve函数的状态改变(注意:需判断当前状态是否可以改变)// 判断当前状态是否可改变if(this.status !== PENDING) return// 改变当前状态this.status = FULFILLED// 保存返回值this.value = value// 执行成功回调while(this.successCallback.length) {this.successCallback.shift()(this.value)}}reject = reason => {// 5. 完成reject函数的状态改变(注意:需判断当前状态是否可以改变)// 判断当前状态是否可改变if(this.status !== PENDING) return// 改变当前状态this.status = REJECTED// 保存返回值this.reason = reason// 执行失败回调while(this.failCallback.length) {this.failCallback.shift()(this.reason)}}// 7. MyPromise类中添加then方法,成功回调有一个参数 表示成功之后的值;失败回调有一个参数 表示失败后的原因then(successCallback, failCallback) {// 14 将then方法的参数变为可选参数successCallback = successCallback ? successCallback : value => this.valuefailCallback = failCallback ? failCallback : reason => {throw this.reason}// 10. 实现then方法链式调用(写一个函数方法专门判断回调的结果是普通值还是promise,then方法返回的仍然是一个promise)let promise2 = new MyPromise((resolve, reject) => {// 判断当前状态 执行对应回调 异步情况下存储当前回调等待执行if(this.status === FULFILLED) {// 异步setTimeout(() => {// 13 then方法捕获错误try {// 异步获取到promise2let x = successCallback(this.value)resolvePromise(promise2, x, resolve, reject)} catch (e) {reject(e)}})} else if(this.status === REJECTED) {// 异步setTimeout(() => {// 13 then方法捕获错误try {// 异步获取到promise2let x = failCallback(this.reason)resolvePromise(promise2, x, resolve, reject)} catch (e) {reject(e)}})} else {// 8. 处理异步逻辑(pending状态下在then中将回调存起来)this.successCallback.push(() => {try {let x = successCallback(this.value)resolvePromise(promise2, x, resolve, reject)} catch(e) {reject(e)}})this.failCallback.push(() => {try {let x = failCallback(this.reason)resolvePromise(promise2, x, resolve, reject)} catch(e) {reject(e)}})}})return promise2}// 17. finally方法 不管成功失败都会执行一次finally(callback) {return this.then(value => {return MyPromise.resolve(callback()).then(() => value)}, reason => {return MyPromise.reject(callback()).then(() => { throw reason })})}// 18. catchcatch(failCallback) {return this.then(undefined, failCallback)}// 15. Promise.allstatic all (array) {let result = []let indexreturn new Promise((resolve, reject) => {function addData(key, value) {result[key] = valueindex++if(index === array.length) {resolve(result)}}for(let i = 0; i < array.length; i++) {let current = array[i]if(current instanceof MyPromise) {current.then(value => addData(i, value), reason => reject(reason))} else {addData(i, array[i])}}})}// 16. Promise.resolve 返回一个promisestatic resolve(value) {if(value instanceof MyPromise) return valuereturn new MyPromise(resolve => resolve(value))}
}// 处理promise返回值各种类型情况(普通值,promise)
function resolvePromise(promise2, x, resolve, reject) {if(promise2 === x) {return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))}if(x instanceof MyPromise) {x.then(resolve, reject)} else {resolve(x)}
}

【对应验证代码】:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script src="./promise2.js"></script><!-- <script src="./newPromise.js"></script> --><script>// 1、基础let promise = new MyPromise((resolve, reject) => {resolve('成功')// reject('失败')})promise.then(value=>{console.log(value)},reason=>{console.log(reason)})// 2、异步let promise = new Promise((resolve, reject) => {setTimeout(() => { // 异步resolve('成功')}, 2000)// reject('失败')})promise.then(value=>{console.log(value)},reason=>{console.log(reason)})// 3、then方法链式调用let promise = new MyPromise((resolve, reject) => {setTimeout(() => { // 异步resolve('成功')}, 2000)// reject('失败')})function other () {return new MyPromise((resolve, reject) => {resolve('other')})}promise.then(value=>{console.log(value)return other()}).then(value => {console.log(value)})// 4、promise对象子返回循环报错var promise = new Promise(function(resolve, reject) {resolve(100)})var p1 = promise.then(function(value) {return p1})p1.then(value => {console.log(value)}, reason => {console.log(reason.message)})// 5、Promise实现捕获错误及then链式调用其他状态代码补充var promise = new MyPromise(function(resolve, reject) {// setTimeout(() => {//   resolve('成功。。。')// },2000)throw new Error('executor error')// resolve('成功')})promise.then(value => {console.log(value)// throw new Error('then error')return 'aaa'}, reason => {console.log('报错')console.log(reason)return '123'}).then(value => {console.log('value2')console.log(value)     }, reason => {console.log('报错2')console.log(reason)})// 6、将then方法的参数变为可选参数var promise = new MyPromise(function(resolve, reject) {resolve(100)})promise.then().then(value => value).then(value => console.log(value))// 7、Promise.all// 按照异步代码调用顺序得到结果// 类直接调用的方法是静态方法function p1() {return new Promise(function (resolve, reject) {setTimeout(function() {resolve('p1')},2000)})}function p2() {return new Promise(function (resolve, reject) {resolve('p2')})}Promise.all(['a', 'b', p1(), p2(), 'c']).then(function(result) {// result -> ['a', 'b', 'p1', 'p2', 'c']console.log(result)})// 8、Promise.resolve将给定的值转换为promise对象function p1() {return new Promise(function (resolve, reject) {resolve('hello')})}Promise.resolve(10).then(value => console.log(value))Promise.resolve(p1()).then(value => console.log(value))// 9、finally方法无论promise执行成功或失败finally都会执行一次// finally方法后可链式调用then方法拿到最终返回的结果function p1() {return new Promise(function (resolve, reject) {reject('hello')})}p1().finally(() => {console.log('finally')}).then(value => {console.log(value)}, reason => {console.log('error')console.log(reason)})// 10、catchfunction p1() {return new Promise(function (resolve, reject) {resolve('hello')})}p1().then(value => {return a}).then(value => console.log('value2:' + value)).catch(reason => console.log('catch:' + reason))</script>
</body>
</html>

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

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

相关文章

图像属性操作

数字图像处理本质是对多维矩阵的操作。按照处理对象不同&#xff0c;可分为黑白图像处理&#xff0c;灰度图像处理&#xff0c;彩色图像处理。按照处理方法分为空间域处理和频域处理。按照策略分为全局处理和局部处理。 #一般步骤输入图像 多维数组 数组运算 图像…

Python3入门基础(03)数据结构

Python3 数据结构 Python3 中有四种标准的数据结构&#xff1a; List&#xff08;列表&#xff09;Tuple&#xff08;元组&#xff09;Set&#xff08;集合&#xff09;Dictionary&#xff08;字典&#xff09; Python 3 的六个标准数据类型中&#xff1a; 不可变数据&…

磨金石教育摄影技能干货分享|优秀艺术类摄影作品欣赏

前面我们分析过纪实类摄影和创意类摄影&#xff0c;艺术类还是第一次讲。 它与纪实类的不同点在于&#xff0c;艺术类摄影更注重作者的主观感受&#xff0c;更侧重个人创造性。 摄影师和画家一样&#xff0c;在经历过人生的挫折、现实与理想交织&#xff0c;内心世界往往是丰富…

塔望3W消费战略案丨聚焦川崎火锅料,回归赛道一梯队

川崎 火锅料 客户&#xff1a;上海新川崎食品有限公司 品牌&#xff1a;川崎 服务&#xff1a;3W消费战略 品牌全案 项目背景 上世纪90年代&#xff0c;一句“吃火锅&#xff0c;没川崎怎么行”&#xff0c;响彻大江南北&#xff0c;让川崎走进千家万户&#xff0c;成为当时…

scaner从外网到内网域渗透笔记

scaner 从外网到内网域渗透 1.环境配置 1.1靶场信息 用到的虚拟机共有三个 分别是 12server-db 、12-dc 、web1 12server-db、web1 这两个可以使用桥接或者nat模式根据需求可以设置 网卡1 12-dc用的是VMnet 19 这台机子已经绑定ip 主机名ip账号和密码web1192.168.0.160we…

我司赤城弘一CEO受邀参加东盟与中日韩中小企业人工智能产业论坛并做主旨发言。

我司赤城弘一CEO受邀参加东盟与中日韩中小企业人工智能产业论坛并做主旨发言。 一、活动背景 为推动东盟与中日韩&#xff08;103&#xff09;中小企业服务联盟务实合作&#xff0c;帮助中小企业提高生产力和技术创新能力&#xff0c;进一步提高国际化发展水平&#xff0c;促进…

2023新一代设备管理系统助力企业高效化巡检

设备数量和种类都比较多的情况下&#xff0c;工厂设备管理员的工作往往压力巨大&#xff0c;因为生产环环相扣&#xff0c;每一个环节如果出现问题&#xff0c;都会影响到生产。如果隐患不能及时处理&#xff0c;会影响设备的正常和安全运转&#xff0c;严重的会波及到周围相关…

Python3 | vscode配置环境

vscode版本&#xff1a;1.74.2python版本&#xff1a;3.9.0win10系统 准备工作&#xff0c;在win10系统 1&#xff0c;安装python3&#xff0c;配置环境变量2&#xff0c;安装vscode 接下来&#xff1a;就可以在vscode配置python环境 1&#xff0c;下载和安装python插件 快…

yapi的安装

Yapi的安装 Yapi是一款不错的接口管理软件&#xff0c;我主要用它来进行接口Mock。 Yapi安装所需环境&#xff1a; Node.js&#xff08;7.6&#xff09;Mongodb&#xff08;2.6&#xff09;git 各环境安装地址&#xff1a; git&#xff1a;https://git-scm.com/downloadsN…

mac vscode安装dart

1.安装Dart 1.安装下载Dart的工具 官网&#xff1a;https://brew.sh/ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"如果遇到 zsh: command not found: brew /bin/zsh -c "$(curl -fsSL https://gite…

【图像算法】pytesseract简单实现图片数字识别

【前置目的】 识别视频中是否包含目标元素&#xff1b; 抽象自动化&#xff0c;就是处理一段含有时间戳的视频&#xff1b; 再核心就是对视频进行图片裁减&#xff0c;识别出图片中的数字&#xff0c;做数学计算延时。 【学习地址】 环境&#xff1a;mac、python3、pytesserac…

强大的ANTLR4(2)

每次在命令行里输入文本有点麻烦&#xff0c;可以将hello slb保存于hello.txt文本文件中&#xff0c;然后运行命令&#xff1a; antlr4-parse Hello.g4 r -tokens hello.txt出现如下内容&#xff1a; [0,0:4hello,<hello>,1:0] [1,6:8slb,<ID>,1:6] [2,9:8<EO…

双脚在路上,钢笔在手里,想法在脑中,2023年CSDN将在心头

☔️&#xff08;一&#xff09;行走过的道路 一年的时间说长不长&#xff0c;说短不短&#xff0c;所渡过时光的长短在于你是否留意你曾走过的路。 &#x1f434;① 记得2022年初我所许下的flag&#xff0c;是要在CSDN平台上运用今年一年的时间撰写超50篇的技术文章&#xff0…

智能家居创意DIY之智能灯泡

一、什么是智能灯 传统的灯泡是通过手动打开和关闭开关来工作。有时&#xff0c;它们可以通过声控、触控、红外等方式进行控制&#xff0c;或者带有调光开关&#xff0c;让用户调暗或调亮灯光。 智能灯泡内置有芯片和通信模块&#xff0c;可与手机、家庭智能助手、或其他智能…

语音转换之CycleGan-VC2:原理与实战

非平行语音转换CycleGAN 之前学习了传统统计学习里的经典的语音转换模型GMM。随着深度学习的发展&#xff0c;出现了更好的语音转换方法&#xff0c;今天学习较为经典的CycleGan。 平行语音转换一般流程 典型代表就是基于GMM的语音转换。平行数据就是说源语音和目标语音一一…

【 Tomcat服务器】

文章目录二、Web服务器2.1 概念2.1.1 什么是Web2.1.2 什么是Web服务器2.2 常见Web服务器2.3 Tomcat服务器2.3.1 Tomcat的下载2.3.2 Tomcat的安装2.3.3 Tomcat的目录结构2.3.4 Tomcat的启动2.3.5 Tomcat的停止运行所需jar包2.3.5 Tomcat的停止2.3.6 修改Tomcat端口号2.3.7 项目部…

美容门店信息化管理系统该如何搭建?不妨参考一下百数

随着人们的生活水平越来越高&#xff0c;人们在解决了温饱问题之后有了更多的追求。其中美容正在成为不少人新的必做项目&#xff0c; 迎合了人们对于爱美的需求。目前我国美容机构市场规模已超过4500亿元&#xff0c;行业从业人员超过3000万。据国家工商联统计数字显示&#x…

宝藏又小众的东方行走rpg制作大师素材网站分享

看到大家都在问东方行走rpg制作大师素材&#xff0c;既要免费又要质量好&#xff0c;数量还要多&#xff0c;小编好不容易挖到了宝藏素材网站哦&#xff0c;资源优质数量庞大&#xff0c;使用体验也很好&#xff0c;要是需要的话&#xff0c;赶紧看一看&#xff0c;小编会给大家…

Redis实现全局唯一id,实现优惠卷秒杀的下单功能

Redis实现全局唯一id public class RedisIdWorker {private StringRedisTemplate stringRedisTemplate;public RedisIdWorker(StringRedisTemplate stringRedisTemplate) {this.stringRedisTemplate stringRedisTemplate;}//开始时间戳private static final long BEGIN_TIMEST…

怎么调图片分辨率?怎么改图片分辨率?

许多考生在提交报名证件照片的时候&#xff0c;都因为图片分辨率不符合规定导致上传失败&#xff0c;所以今天小编就来告诉大家如何调整图片分辨率&#xff0c;其实只要通过专业的图片修改分辨率工具就可以轻松解决。这里推荐一款在线修改分辨率的软件&#xff0c;不用下载即可…