当前位置: 首页 > news >正文

从零开始手写一个Promise,彻底理解异步编程的核心原理

promise A+规范:

在promiseA+中,把每一个异步任务都看做一个promise对象,每一个任务对象都有两个阶段(unsettled,settled),三个状态(pending,resolved,rejected,)

两个阶段:

  • unsettled:事情未解决阶段,事情还没有结果。
  • settled:事情已解决阶段,无论是成功,还是失败,已经有结果了。

三个状态:

  • padding:挂起,处于未解决阶段。事情还没有结果输出,promise对象为挂起状态。
  • resolved:已处理,处于已解决阶段。已经有了成功的结果,可以按照正常逻辑进行下去,并可以传递一个成功信息,后续可以用.then的onFulfiled处理。
  • rejected:已拒绝,处于已解决阶段,已经有了失败的结果,无法按照正常逻辑进行下去,可以传递一个错误信息,后续可以用.then的onRejected处理,或使用catch处理。

两个阶段是由unsettle -> settled,不可逆。

三个状态是由padding -> resolved/rejected,不可逆,且resolved和rejected之间的状态不可以互相切换。

也就是说,promise对象一旦有了结果,结果不可改变,不可消失。

手写Promise

/*** 自定义Promise实现,严格遵循Promise/A+规范* 使用微任务(queueMicrotask)进行异步调度* 状态:pending, fulfilled, rejected*/
class MyPromise {// 定义Promise的三种状态(静态常量)static PENDING = 'pending';static FULFILLED = 'fulfilled';static REJECTED = 'rejected';/*** 构造函数* @param {Function} executor 执行器函数(resolve, reject) => {}*/constructor(executor) {// ==== 初始化状态和数据 ====this.state = MyPromise.PENDING;   // 初始状态this.value = null;                // 成功时传递的值this.reason = null;               // 失败时传递的原因this.onFulfilledCallbacks = [];   // 成功回调队列this.onRejectedCallbacks = [];    // 失败回调队列// ==== 定义resolve函数 ====const resolve = (value) => {// 状态只能从pending变更if (this.state === MyPromise.PENDING) {// 处理MyPromise实例if (value instanceof MyPromise) {value.then(resolve, reject);return;}// 处理thenable对象(符合Promise/A+规范的thenable)if (value && typeof value.then === 'function') {// 使用微任务确保异步执行queueMicrotask(() => {try {value.then(y => resolve(y),r => reject(r));} catch (error) {reject(error);}});return;}// 更新状态和数据this.state = MyPromise.FULFILLED;this.value = value;// 执行所有成功回调(微任务调度)this._executeCallbacks(this.onFulfilledCallbacks);}};// ==== 定义reject函数 ====const reject = (reason) => {// 状态只能从pending变更if (this.state === MyPromise.PENDING) {this.state = MyPromise.REJECTED;this.reason = reason;// 执行所有失败回调(微任务调度)this._executeCallbacks(this.onRejectedCallbacks);}};// ==== 立即执行executor ====try {executor(resolve, reject);} catch (error) {// 捕获同步执行错误reject(error);}}/*** 内部方法:执行回调队列(使用微任务调度)* @param {Array} callbacks 回调函数队列*/_executeCallbacks(callbacks) {// 使用微任务API调度执行queueMicrotask(() => {// 遍历执行所有回调callbacks.forEach(callback => {callback();});// 清空数组(更高效的实现)callbacks.length = 0;});}/*** Promise核心方法:注册fulfilled/rejected状态回调* @param {Function} onFulfilled 成功回调* @param {Function} onRejected 失败回调* @returns {MyPromise} 新的Promise实例*/then(onFulfilled, onRejected) {// ==== 参数规范化 ====// 透传值:如果不是函数,创建默认透传函数onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;// 透传错误:如果不是函数,创建默认抛出函数onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason; };// ==== 创建新Promise ====const promise2 = new MyPromise((resolve, reject) => {// ==== 统一处理回调 ====const handleCallback = (callback, valueOrReason) => {queueMicrotask(() => {try {const x = callback(valueOrReason);// 解析Promise链resolvePromise(promise2, x, resolve, reject);} catch (error) {reject(error);}});};// ==== 状态处理 ====switch (this.state) {case MyPromise.FULFILLED:// 直接异步执行成功回调handleCallback(onFulfilled, this.value);break;case MyPromise.REJECTED:// 直接异步执行失败回调handleCallback(onRejected, this.reason);break;case MyPromise.PENDING:// 添加包装后的回调到队列this.onFulfilledCallbacks.push(() => handleCallback(onFulfilled, this.value));this.onRejectedCallbacks.push(() => handleCallback(onRejected, this.reason));break;}});return promise2;}/*** 捕获Promise链中的错误(语法糖)* @param {Function} onRejected 错误处理函数* @returns {MyPromise} 新的Promise实例*/catch(onRejected) {return this.then(null, onRejected);}/*** 无论成功失败都会执行的回调* @param {Function} callback 终态回调函数* @returns {MyPromise} 新的Promise实例*/finally(callback) {return this.then(value => MyPromise.resolve(callback()).then(() => value),reason => MyPromise.resolve(callback()).then(() => { throw reason }));}// ========== 静态方法 ========== ///*** 创建已解决的Promise* @param {any} value 解决值* @returns {MyPromise} 已解决的Promise*/static resolve(value) {// 如果是Promise实例直接返回if (value instanceof MyPromise) {return value;}// 包装普通值return new MyPromise(resolve => resolve(value));}/*** 创建已拒绝的Promise* @param {any} reason 拒绝原因* @returns {MyPromise} 已拒绝的Promise*/static reject(reason) {return new MyPromise((_, reject) => reject(reason));}/*** 等待所有Promise完成(全部成功才算成功)* @param {Iterable} promises Promise集合* @returns {MyPromise} 包含所有结果的Promise*/static all(promises) {// 转换为数组处理const promisesArray = Array.from(promises);return new MyPromise((resolve, reject) => {const results = [];let count = 0;const len = promisesArray.length;// 空数组立即解决if (len === 0) {resolve(results);return;}promisesArray.forEach((p, i) => {MyPromise.resolve(p).then(value => {results[i] = value;if (++count === len) resolve(results);},reject  // 任一失败立即拒绝);});});}/*** 竞速Promise(第一个落定的结果)* @param {Iterable} promises Promise集合* @returns {MyPromise} 第一个落定结果的Promise*/static race(promises) {// 转换为数组处理const promisesArray = Array.from(promises);return new MyPromise((resolve, reject) => {promisesArray.forEach(p => {MyPromise.resolve(p).then(resolve, reject);});});}/*** 等待所有Promise落定(无论成功失败)* @param {Iterable} promises Promise集合* @returns {MyPromise} 包含所有结果的Promise*/static allSettled(promises) {// 转换为数组处理const promisesArray = Array.from(promises);return new MyPromise(resolve => {const results = [];let count = 0;const len = promisesArray.length;// 完成检查函数const checkComplete = () => {if (count === len) resolve(results);};// 空数组立即解决if (len === 0) {resolve(results);return;}promisesArray.forEach((p, i) => {MyPromise.resolve(p).then(value => {results[i] = { status: 'fulfilled', value };count++;checkComplete();},reason => {results[i] = { status: 'rejected', reason };count++;checkComplete();});});});}/*** 取第一个成功的Promise(全部失败才拒绝)* @param {Iterable} promises Promise集合* @returns {MyPromise} 第一个成功的Promise*/static any(promises) {// 转换为数组处理const promisesArray = Array.from(promises);return new MyPromise((resolve, reject) => {const errors = [];let count = 0;const len = promisesArray.length;// 空数组立即拒绝if (len === 0) {reject(new Error('All promises were rejected'));return;}promisesArray.forEach((p, i) => {MyPromise.resolve(p).then(resolve,  // 第一个成功立即解决reason => {errors[i] = reason;if (++count === len) {// 创建聚合错误const error = new Error('All promises were rejected');error.errors = errors;reject(error);}});});});}
}/*** Promise解决过程(符合Promise/A+规范)* @param {MyPromise} promise2 新Promise实例* @param {any} x 前一个Promise的返回值* @param {Function} resolve 解决函数* @param {Function} reject 拒绝函数*/
function resolvePromise(promise2, x, resolve, reject) {// ==== 1. 循环引用检测(放在最前面)====if (promise2 === x) {return reject(new TypeError('Chaining cycle detected for promise'));}// ==== 2. 防止多次调用 ====let called = false;// ==== 3. 处理Promise/thenable对象 ====if ((x !== null && typeof x === 'object') || typeof x === 'function') {try {// ==== 3.1 获取then方法 ====const then = x.then;// ==== 3.2 处理thenable对象 ====if (typeof then === 'function') {then.call(x,// 成功回调y => {if (called) return;called = true;// 递归解析直到非thenableresolvePromise(promise2, y, resolve, reject);},// 失败回调r => {if (called) return;called = true;reject(r);});} else {// ==== 3.3 普通对象直接解决 ====resolve(x);}} catch (error) {// ==== 3.4 异常处理 ====if (called) return;called = true;reject(error);}} else {// ==== 4. 基本类型值直接解决 ====resolve(x);}
}

http://www.xdnf.cn/news/730081.html

相关文章:

  • 如何获取Minio元数据
  • 每日八股文5.30
  • 谷云科技发布业内首份 Oracle OSB 迁移到 iPaaS 技术白皮书
  • 40. 自动化异步测试开发之编写异步业务函数、测试函数和测试类(类写法)
  • Delphi读写Mifare Desfire Ev1 Ev2 EV3卡修改AES密钥源码
  • 39. 自动化异步测试开发之编写异步业务函数、测试函数和测试类(函数写法)
  • 逆向分析基础总结
  • HTML 文件反编译指南:优化与学习网页代码
  • 【容器docker】启动容器kibana报错:“message“:“Error: Cannot find module ‘./logs‘
  • STUSB4500 PPS(PD3.0)快充SINK模块——应用 解析
  • [学习] C语言的回调函数(代码示例)
  • 数据基座觉醒!大数据+AI如何重构企业智能决策金字塔(下)
  • 【Linux 学习计划】-- 命令行参数 | 环境变量
  • 【目标检测】【AAAI-2022】Anchor DETR
  • 【Golang进阶】第八章:并发编程基础——从Goroutine调度到Channel通信实战
  • Redis持久化机制
  • MPC5744P——eTimer简介
  • Github 2025-05-30Java开源项目日报Top10
  • 《深入解析Go语言结构:简洁高效的工程化设计》
  • 基于 KubeKey 3.1.9,快速部署 K8s 1.33.0 高可用集群
  • Java复习Day23
  • haproxy 搭建web群集
  • EMQX社区版5.8.5集群搭建踩坑记
  • vscode命令行debug
  • 中国外卖包装废弃物高精度网格图谱(Tif/Excel/Shp)
  • 128、STM32H723ZGT6实现串口IAP
  • 贪心算法实战3
  • 6年“豹变”,vivo S30系列引领手机进入场景“体验定义”时代
  • 交叉编译tcpdump工具
  • File—IO流