手写 ES6 Promise() 相关函数 手写 Promise() 相关函数Promise()、then()、catch()、finally()// 定义三种状态常量constPENDINGpendingconstFULFILLEDfulfilledconstREJECTEDrejectedclassMyPromise{/* 定义状态和结果两个私有属性: 1.使用 # 语法ES2022 官方私有字段在类中通过 # 前缀声明属性该属性仅在类的内部可访问 2.Symbol 作为属性键用 Symbol 作为属性名外部无法直接获取 Symbol 引用。 */#statePENDING// 状态#resultundefined// 结果#thenables[]// 存储 then 方法回调的队列constructor(executor){// resolve 和 reject 主要功能即为改变状态设置结果constresolve(value){// 解决时调用this.#changeState(FULFILLED,value)}constreject(reason){// 拒绝时调用this.#changeState(REJECTED,reason)}try{// 只能捕获同步错误无法捕获异步错误如 setTimeout 里的错误executor(resolve,reject)}catch(err){reject(err)}}// 改变状态和设置结果的私有方法#changeState(state,result){if(this.#state!PENDING)returnthis.#statestatethis.#resultresultthis.#run()}// 处理 then 回调的私有方法#handleCallback(callback,resolve,reject){if(typeofcallback!function){// 状态穿透即 then 方法返回的 Promise 状态与当前 Promise 状态保持一致// then 回调是微任务需要放到微任务队列中执行queueMicrotask((){// 参考https://developer.mozilla.org/zh-CN/docs/Web/API/Window/queueMicrotaskconstsettledthis.#stateFULFILLED?resolve:rejectsettled(this.#result)})return}queueMicrotask((){try{constresultcallback(this.#result)// 如果返回值是一个 Promise则等待它完成后再 resolveif(resultinstanceofMyPromise){result.then(resolve,reject)}else{resolve(result)}}catch(err){reject(err)}})}/* 执行队列的私有方法两个执行时机 1.Promise 状态改变时 2.then 方法被调用时 */#run(){if(this.#statePENDING)return// 取出队列中的回调函数依次执行(先进先出原则)while(this.#thenables.length){const{onFulfilled,onRejected,resolve,reject}this.#thenables.shift()try{if(this.#stateFULFILLED){// 执行 onFulfilled 回调函数this.#handleCallback(onFulfilled,resolve,reject)}else{// 执行 onRejected 回调函数this.#handleCallback(onRejected,resolve,reject)}}catch(err){reject(err)}}}/* onFulfilled 可选一个在此 Promise 对象被兑现时异步执行的函数。它的返回值将成为 then() 返回的 Promise 对象的兑现值。 onRejected 可选一个在此 Promise 对象被拒绝时异步执行的函数。它的返回值将成为 catch() 返回的 Promise 对象的兑现值。 */then(onFulfilled,onRejected){returnnewMyPromise((resolve,reject){// 将四个回调函数放入队列以便立即或将来处理this.#thenables.push({onFulfilled,onRejected,resolve,reject})// 启动队列处理this.#run()})}catch(onRejected){returnthis.then(undefined,onRejected)}finally(onFinally){this.then((value){MyPromise.resolve(onFinally()).then(()value)},(reason){MyPromise.resolve(onFinally()).then((){throwreason})})}}验证测试 MyPromise() 函数constp1newPromise((resolve,reject){resolve(1)reject(2)})console.log(p1,p1)constp2newPromise((){throw123})console.log(p2,p2)constp3newPromise((resolve,reject){setTimeout((){resolve(setTimeout)// 无法捕获},0)})console.log(p3,p3)constmyP1newMyPromise((resolve,reject){resolve(1)reject(2)})console.log(myP1,myP1)myP1.then((res){console.log(res,res)// 1returnres1},(err){console.log(err,err)// 1}).then((res){console.log(res,res)// 2// throw errorreturnres1}).then((res){console.log(res,res)// 3}).catch((err){console.log(err,err)}).finally((){console.log(finally)})constmyP2newMyPromise((){throw123})console.log(myP2,myP2)constmyP3newMyPromise((resolve,reject){setTimeout((){resolve(setTimeout)// 无法捕获},0)})console.log(myP3,myP3)执行结果