找回密码
 立即注册
首页 业界区 安全 JS基于Promises/A+规范实现一个Promise

JS基于Promises/A+规范实现一个Promise

况雪柳 2025-7-6 16:02:05
   本文基于Promises/A+实现一个Promise对象,帮助大家理解使用它。
  说明一下,Promises/A+是ES6中Promise的前身,规范可以参考:https://promisesaplus.com/
  ES6白皮书参考地址:https://tc39.es/ecma262/#sec-promise-objects
  MDN文档:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise
  首先,根据Promises/A+规范,定义了一些术语,重要的就Promise和Thenable:  
  1.     Promise是一个具有then方法的对象或者函数,这个then方法需要满足后面的一些规范。
  2.     Thenable是一个具有then方法的对象或者函数。
复制代码
  从上面的术语可以看到,Promise是Thenable,但是Thenable不一定是Promise,主要区别有两点:
  1. Promise对象具有三个状态:pending, fulfilled, rejected  
  1.     1、当状态是pending时,Promise的状态可以变为fulfilled或者rejected。
  2.     2、当状态是fulfilled时,Promise的状态不可再改变,并具有一个不可改变的结果,结果可以是null、undefined、对象、函数、Promise或者Thenable等。
  3.     3、当状态是rejected时,Promise的状态不可再改变,并可具有一个不可改变的原因,原因可以是null、undefined、对象、函数、Promise或者Thenable等。
复制代码
   2. Promise对象需要提供一个then方法,这个then方法需要接收两个参数:   
  1.     promise.then(onFulfilled, onRejected)
  2.    
  3.     //onFulfilled是当promise状态从pending变为fulfilled后需要执行的函数
  4.     //onRejected是当promise状态从pending变为rejected后需要执行的函数
复制代码
  而在ES6的规范中,Promise不仅满足上面Promises/A+规范,还有其他一些特性来保证Promise的实用性,比如ES6中,Promise的构造函数需要传入一个executor函数参数,它接收两个函数作为参数:resolveFunc 和 rejectFunc,分别表示将Promise的状态置为fulfilled还是rejected,因此,我们可以写出Promise的构造函数大概是这个样子的:
  1.     class MyPromise {
  2.         constructor(executor) {
  3.             //表示状态是否已指定,保证状态只会被改变一次
  4.             let specified = false
  5.             //状态
  6.             let state = PENDING
  7.             //结果或者原因
  8.             let value = void 0
  9.             //fulfilled状态的回调函数
  10.             let onFulfilledCallbacks = []
  11.             //rejected状态的回调函数
  12.             let onRejectedCallbacks = []
  13.             //resolve函数,改变状态为fulfilled
  14.             const resolve = (result) => { }
  15.             //reject函数,改变状态为rejected
  16.             const reject = (reason) => { }
  17.             //then方法
  18.             this.then = (onFulfilled, onRejected) => { }
  19.             try {
  20.                 executor(resolve, reject)
  21.             } catch (error) {
  22.                 reject(error) //如果executor抛出异常,那么直接reject
  23.             }
  24.         }
  25.     }
复制代码
  上面只是Promise大致的样子,接下来我们就需要去实现这几个函数即可:resolve、reject、then方法
  首先,我们需要先定义一些通用的函数与变量:  
  1.     //Promise的三个状态
  2.     const PENDING = 'pending'
  3.     const FULFILLED = 'fulfilled'
  4.     const REJECTED = 'rejected'
  5.     //判断一个值是否是一个函数
  6.     const isFunction = value => value && typeof value === 'function' && value instanceof Function
  7.     //判断一个值是否是一个Promise
  8.     const isPromise = value => value && (value instanceof MyPromise || value instanceof Promise)
  9.     //判断一个值是否是一个对象
  10.     const isObject = value => value && typeof value === 'object' && value instanceof Object
  11.     //执行微任务,没有返回结果
  12.     function runMicroTask(fn) {
  13.         //首先看微任务队列函数是否存在,如果存在则使用微任务队列执行
  14.         if (isFunction(queueMicrotask)) {
  15.             runMicroTask = f => queueMicrotask(f)
  16.         } else if (isObject(process) && isFunction(process.nextTick)) { //如果是Node.js环境
  17.             runMicroTask = f => process.nextTick(f)
  18.         } else if (isFunction(MutationObserver)) { //如果是浏览器环境
  19.             runMicroTask = f => {
  20.                 const observer = new MutationObserver(f)
  21.                 const node = document.createTextNode('')
  22.                 observer.observe(node, { characterData: true })
  23.                 node.data = '1' //触发MutationObserver
  24.             }
  25.         } else { //如果都不存在,那么使用setTimeout(fn, 0)执行
  26.             runMicroTask = f => setTimeout(f, 0)
  27.         }
  28.         runMicroTask(fn)
  29.     }
复制代码
  reject函数
  reject函数的视线很简单,就是变更Promise的状态和结果即可,结果往往是一个Error对象:  
  1.     //reject函数,改变状态为rejected
  2.     const reject = (reason) => {
  3.         //当且仅当状态是pending且未指定时进入
  4.         if (state === PENDING && !specified) {
  5.             [state, value, specified] = [REJECTED, reason, true]
  6.             //rejected状态的回调函数,将其添加到onRejectedCallbacks数组中,判断是否执行回调函数
  7.             runOrQueueTasks(onRejectedCallbacks, REJECTED)
  8.         }
  9.     }
复制代码
  这里runOrQueueTasks其实就是将回调函数放到微任务里并准备执行回调函数,实现如下:  
  1.     const runOrQueueTasks = (callbacks, requireState, callback) => {
  2.         //如果callback是函数,那么将其添加到callbacks数组中
  3.         callback && callbacks.push(callback)
  4.         //如果是指定状态,那么使用微任务执行
  5.         if (state === requireState) {
  6.             while (callbacks.length) {
  7.                 const cb = callbacks.shift()
  8.                 runMicroTask(() => cb(value)) // 使用微任务执行
  9.             }
  10.         }
  11.     }
复制代码
  resolve函数
  resolve的函数实现逻辑更多一些,具体可以看看MDN的说明(跳转),总结下来就是:  
  1.     1、resolve函数接收一个结果对象result
  2.     2、如果result结果对象是当前Promise自身,那么将会reject一个TypeError
  3.     3、如果result结果对象不是一个Thenable对象,那么Promise将会被立即FULFILLED,并采用这个result作为结果
  4.     4、如果result结果对象是一个Thenable对象,那么将会把Thenable对象的then方法放到微任务去执行,并Promise的resolve和reject作为then方法的两个参数传进入(近似可以这么认为),就是说Promise的结果又Thenable决定
复制代码
  因此我们的resolve函数大概是这个样子的:  
  1.     //resolve函数,改变状态为fulfilled
  2.     const resolve = (result) => {
  3.         //当且仅当状态是pending且未指定时进入
  4.         if (state === PENDING && !specified) {
  5.             //如果传入的是当前Promise对象,那么直接reject
  6.             if (result === this) {
  7.                 return reject(new TypeError('Chaining cycle detected for promise'))
  8.             }
  9.             specified = true;
  10.             //如果result是Thenable,那么调用(ES6白皮书)
  11.             //如果result是一个Promise,那么吸收它的状态
  12.             try {
  13.                 if (result && isFunction(result.then)) {
  14.                     return runMicroTask(() => {
  15.                         try {
  16.                             const res = r => (specified = false, resolve(r)) //临时打开
  17.                             const rej = r => (specified = false, reject(r))  //临时打开            
  18.                             result.then(res, rej)
  19.                         } catch (error) {
  20.                             reject(error)
  21.                         }
  22.                     })
  23.                 }
  24.             } catch (error) {
  25.                return reject(error) //如果result.then抛出异常,那么直接reject
  26.             }
  27.             [state, value] = [FULFILLED, result]
  28.             //fulfilled状态的回调函数,将其添加到onFulfilledCallbacks数组中,判断是否执行回调函数
  29.             runOrQueueTasks(onFulfilledCallbacks, FULFILLED)
  30.         }
  31.     }
复制代码
  then方法 
  根据Promises/A+规范,then方法需要满足下面的:  
  1.     1、调用方式:promise.then(onFulfilled, onRejected),这里onFulfilled、onRejected都必须是函数,否则将被忽略
  2.     2、onFulfilled、onRejected需要分别在promise变为fulfilled和rejected后执行,将结果或者原因作为第一个参数传入,并且至多执行一次
  3.     3、onFulfilled、onRejected不能在当前上下文中执行,需要放到setTimeout、微任务这样的上下文去执行
  4.     4、then方法如果调用多次,onFulfilled和onRejected需要按他们所在的then方法的调用顺序依次执行
  5.     5、then方法方法需要返回一个新的Promise对象:promise2 = promise1.then(onFulfilled, onRejected)
  6.         1、如果onFulfilled和onRejected返回一个值x,那么将执行Promise Resolution Procedure,将promise2和x作为参数传入
  7.         2、如果onFulfilled或者onRejected抛出异常,那么promise2将会使用这个异常进行reject
  8.         3、如果onFulfilled不是函数且promise1状态是fulfilled,或者onRejected不是函数且promise1状态是rejected,那么promise2将会吸收promise1的状态,即promise1和promise2保持相同的结果和状态
复制代码
   因为then方法的实现大致如下
  1.     //then方法
  2.     this.then = (onFulfilled, onRejected) => {
  3.         const promise = new (this.constructor[Symbol.species] || MyPromise)((resolve, reject) => {
  4.             //如果onFulfilled是函数则调用
  5.             state !== REJECTED && runOrQueueTasks(onFulfilledCallbacks, FULFILLED, isFunction(onFulfilled) ? value => {
  6.                 try {
  7.                     const x = onFulfilled(value)
  8.                     //根据函数返回结果进行Promise Resolution Procedure过程
  9.                     promiseResolutionProcedure(promise, x, resolve, reject)
  10.                 } catch (error) {
  11.                     reject(error)
  12.                 }
  13.             } : resolve)//否则根据当前状态直接resolve
  14.             //如果onRejected是函数则调用
  15.             state !== FULFILLED && runOrQueueTasks(onRejectedCallbacks, REJECTED, isFunction(onRejected) ? value => {
  16.                 try {
  17.                     const x = onRejected(value)
  18.                     //根据函数返回结果进行Promise Resolution Procedure过程
  19.                     promiseResolutionProcedure(promise, x, resolve, reject)
  20.                 } catch (error) {
  21.                     reject(error)
  22.                 }
  23.             } : reject)//否则根据当前状态直接reject
  24.         })
  25.         return promise
  26.     }
复制代码
   这里说下Promise Resolution Procedure过程
  1.     Promise Resolution Procedure过程采用这个表达方式:[[Resolve]](promise, x),其实可以理解为就是个函数处理过程,表示promise怎么去根据x的值变更状态
  2.     1、如果promise和x是相同的对象,那么promise将会被reject(TypeError)
  3.     2、如果x是一个Promise,那么promise对象将会吸收x的状态,即promise和x保持相同的结果和状态
  4.     3、如果x是一个Thenable,那么调用Thenable的then方法,并将promise的resolve和reject函数作为参数传入then方法调用
  5.         1、如果resolve函数被调用,并接收到结果y,那么接着执行Promise Resolution Procedure过程:[[Resolve]](promise, y)
  6.         2、如果reject函数被调用,那么接收到结果r,那么promise将会被reject(r)
  7.         3、resolve和reject函数只能被调用一次
  8.         4、如果then方法调用报错,且resolve和reject函数都未被调用,那么promise将会被reject
  9.     4、否则promise将会被resolve(x)
复制代码
  大致的实现代码是这个样子的:  
  1.     //Promise状态处理过程
  2.     const promiseResolutionProcedure = (promise, x, resolve, reject) => {
  3.         // promise和x不能引用同一个对象
  4.         if (promise === x) {
  5.             throw new TypeError('Chaining cycle detected for promise')
  6.         }
  7.         //如果x是一个Promise,那么promise对象直接吸收x的状态
  8.         if (isPromise(x)) { //这里兼容一下原生Promise
  9.             //这里ES6白皮书是放到微队列中执行的(PromiseA+规范没有确定)
  10.             return runMicroTask(() => x.then(resolve, reject))
  11.         }
  12.         //如果x是对象或者函数
  13.         if (isObject(x) || isFunction(x)) {
  14.             let ignoreCall = false
  15.             try {
  16.                 //取then方法报错,那么直接reject
  17.                 let then = x.then
  18.                 //如果then是一个函数,那么调用then方法
  19.                 if (isFunction(then)) {
  20.                     //调用采用x作为this,并传入两个参数resolve和reject,并要求resolve和reject只能调用一次
  21.                     return runMicroTask(() => then.call(x, y => {
  22.                         ignoreCall = ignoreCall || !promiseResolutionProcedure(promise, y, resolve, reject)
  23.                     }, r => {
  24.                         ignoreCall = ignoreCall || !reject(r)
  25.                     }))
  26.                 }
  27.             } catch (error) {
  28.                 //如果then方法已经调用了resolve或reject,那么直接忽略
  29.                 ignoreCall || reject(error)
  30.             }
  31.         }
  32.         //如果x不是一个对象或者函数,那么直接resolve
  33.         resolve(x)
  34.     }
复制代码
   注:这里then方法的实现是参考Promises/A+规范,MDN上的描述大致含义和这个差不多,感兴趣的可以去看看(跳转)
  到这里我们的Promise就已经实现了,接下来说说Promise其它方法的拓展,这部分不是Promises/A+规范的内容,是ES6的Promise的拓展
  catch函数
  catch函数可以参考MDN上面的说明(跳转),而我们的实现如下:  
  1.     class MyPromise {
  2.         //...其它代码
  3.         
  4.         //以下是ES6白皮书的拓展,不是Promise A+规范的内容
  5.         catch(onRejected) {
  6.             return this.then(null, onRejected)
  7.         }
  8.     }
复制代码
  finally函数
  finally函数可以参考MDN上面的说明(跳转),而我们的实现如下:
  1.     class MyPromise {
  2.         //...其它代码
  3.         
  4.         finally(onFinally) {
  5.             //onFinally是一个不接收任何参数的函数
  6.             //如果 onFinally 抛出错误或返回被拒绝的 promise,则新的 promise 将使用该值进行拒绝
  7.             const onThen = isFunction(onFinally)?() => {
  8.                 const result = onFinally()
  9.                 if (isPromise(result)) {
  10.                     return result.then(() => this, () => result)
  11.                 }
  12.                 return this;
  13.             } : onFinally
  14.             return this.then(onThen, onThen)
  15.         }
  16.     }
复制代码
  resolve函数
  resolve函数可以参考MDN上面的说明(跳转),而我们的实现如下:  
  1.     class MyPromise {
  2.         //...其它代码
  3.         
  4.         static resolve(value) {
  5.             //如果value是一个Promise,那么直接返回
  6.             if (isPromise(value)) {
  7.                 return value
  8.             }
  9.             //使用call(this)用以支持非Promise构造器(ES6白皮书)
  10.             const { promise, resolve } = MyPromise.withResolvers.call(this)
  11.             resolve(value) //直接resolve
  12.             return promise
  13.         }
  14.     }
复制代码
  reject函数
  reject函数可以参考MDN上面的说明(跳转),而我们的实现如下: 
  1.     class MyPromise {
  2.         //...其它代码
  3.         
  4.         static reject(reason) {
  5.             //使用call(this)用以支持非Promise构造器(ES6白皮书)
  6.             const { promise, reject } = MyPromise.withResolvers.call(this)
  7.             reject(reason) //直接reject
  8.             return promise
  9.         }
  10.     }
复制代码
  all函数
  all函数可以参考MDN上面的说明(跳转),而我们的实现如下: 
  1.     class MyPromise {
  2.         //...其它代码
  3.         
  4.         static all(promises) {
  5.             promises = [...promises]
  6.             const { promise, resolve, reject } = MyPromise.withResolvers()
  7.             const results = []
  8.             //如果是空数组,那么直接返回一个resolved的Promise
  9.             if (!promises.length) {
  10.                 resolve(results)
  11.             } else {
  12.                 promises.forEach((p, i) => {
  13.                     MyPromise.resolve(p).then(value => {
  14.                         results[i] = value
  15.                         promises.pop() //每执行完成就弹出一个进行计数
  16.                         //如果全部已经是fulfilled状态,那么resolve结果
  17.                         promises.length || resolve(results)
  18.                     }, reject)
  19.                 })
  20.             }
  21.             return promise
  22.         }
  23.     }
复制代码
  race函数
  race函数可以参考MDN上面的说明(跳转),而我们的实现如下:
  1.     class MyPromise {
  2.         //...其它代码
  3.         
  4.         static race(promises) {
  5.             promises = [...promises]
  6.             const { promise, resolve, reject } = MyPromise.withResolvers()
  7.             //只要有一个是fulfilled或者rejected,那么当前Promise就需要改变状态
  8.             promises.forEach(p => MyPromise.resolve(p).then(resolve, reject))
  9.             return promise
  10.         }
  11.     }
复制代码
  allSettled函数
  allSettled函数可以参考MDN上面的说明(跳转),而我们的实现如下:
  1.     class MyPromise {
  2.         //...其它代码
  3.         
  4.         static allSettled(promises) {
  5.             promises = [...promises]
  6.             const { promise, resolve } = MyPromise.withResolvers()
  7.             const results = []
  8.             //如果是空数组,那么直接返回一个resolved的Promise
  9.             if (!promises.length) {
  10.                 resolve(results)
  11.             } else {
  12.                 promises.forEach((p, i) => {
  13.                     MyPromise.resolve(p).then(value => {
  14.                         results[i] = { status: FULFILLED, value }
  15.                         promises.pop() //每执行完成就弹出一个进行计数
  16.                         //全部Promise已经是fulfilled或者rejected状态了,那么resolve
  17.                         promises.length || resolve(results)
  18.                     }, reason => {
  19.                         results[i] = { status: REJECTED, reason }
  20.                         promises.pop() //每执行完成就弹出一个进行计数
  21.                         //全部Promise已经是fulfilled或者rejected状态了,那么resolve
  22.                         promises.length || resolve(results)
  23.                     })
  24.                 })
  25.             }
  26.             return promise
  27.         }
  28.     }
复制代码
  any函数
  any函数可以参考MDN上面的说明(跳转),而我们的实现如下:
  1.     class MyPromise {
  2.         //...其它代码
  3.         
  4.         static any(promises) {
  5.             promises = [...promises]
  6.             const { promise, resolve, reject } = MyPromise.withResolvers()
  7.             const errors = []
  8.             //如果是空数组,那么直接返回一个rejected的Promise
  9.             if (!promises.length) {
  10.                 reject(new AggregateError(errors, 'All promises were rejected'))
  11.             } else {
  12.                 promises.forEach((p, i) => {
  13.                     MyPromise.resolve(p).then(resolve, reason => {
  14.                         errors[i] = reason
  15.                         promises.pop() //每执行完成就弹出一个进行计数
  16.                         //如果有rejected,那么收集所有rejected并最后全局reject
  17.                         promises.length || reject(new AggregateError(errors, 'All promises were rejected'))
  18.                     })
  19.                 })
  20.             }
  21.             return promise
  22.         }
  23.     }
复制代码
  try函数
  try函数可以参考MDN上面的说明(跳转),而我们的实现如下:  
  1.     class MyPromise {
  2.         //...其它代码
  3.         
  4.         static try(fn, ...args) {
  5.             //使用call(this)用以支持非Promise构造器(ES6白皮书)
  6.             const { promise, resolve, reject } = MyPromise.withResolvers.call(this)
  7.             try {
  8.                 const result = fn(...args)
  9.                 resolve(result)
  10.             } catch (error) {
  11.                 reject(error)
  12.             }
  13.             return promise
  14.         }
  15.     }
复制代码
  withResolvers函数
  withResolvers函数可以参考MDN上面的说明(跳转),而我们的实现如下:
  1.     class MyPromise {
  2.         //...其它代码
  3.         
  4.         static withResolvers() {
  5.             let resolve, reject
  6.             const promise = new this((res, rej) => {
  7.                 resolve = res
  8.                 reject = rej
  9.             })
  10.             return { promise, resolve, reject }
  11.         }
  12.     }
复制代码
  最后附上自己实现的Promise完整代码:
查看代码
  1.     //Promise的三个状态
  2.     const PENDING = 'pending'
  3.     const FULFILLED = 'fulfilled'
  4.     const REJECTED = 'rejected'
  5.     //判断一个值是否是一个函数
  6.     const isFunction = value => value && typeof value === 'function' && value instanceof Function
  7.     //判断一个值是否是一个Promise
  8.     const isPromise = value => value && (value instanceof MyPromise || value instanceof Promise)
  9.     //判断一个值是否是一个对象
  10.     const isObject = value => value && typeof value === 'object' && value instanceof Object
  11.     //执行微任务,没有返回结果
  12.     function runMicroTask(fn) {
  13.         //首先看微任务队列函数是否存在,如果存在则使用微任务队列执行
  14.         if (isFunction(queueMicrotask)) {
  15.             runMicroTask = f => queueMicrotask(f)
  16.         } else if (isObject(process) && isFunction(process.nextTick)) { //如果是Node.js环境
  17.             runMicroTask = f => process.nextTick(f)
  18.         } else if (isFunction(MutationObserver)) { //如果是浏览器环境
  19.             runMicroTask = f => {
  20.                 const observer = new MutationObserver(f)
  21.                 const node = document.createTextNode('')
  22.                 observer.observe(node, { characterData: true })
  23.                 node.data = '1' //触发MutationObserver
  24.             }
  25.         } else { //如果都不存在,那么使用setTimeout(fn, 0)执行
  26.             runMicroTask = f => setTimeout(f, 0)
  27.         }
  28.         runMicroTask(fn)
  29.     }    class MyPromise {        constructor(executor) {            //表示状态是否已指定,保证状态只会被改变一次            let specified = false            //状态            let state = PENDING            //结果或者原因            let value = void 0            //fulfilled状态的回调函数            let onFulfilledCallbacks = []            //rejected状态的回调函数            let onRejectedCallbacks = []            //如果想看promise运行的状态和结果,可以使用下面的代码            Object.defineProperty(this, 'state', { get() { return state }, configurable: false, enumerable: false })            Object.defineProperty(this, 'value', { get() { return value }, configurable: false, enumerable: false })            const runOrQueueTasks = (callbacks, requireState, callback) => {                //如果callback是函数,那么将其添加到callbacks数组中                callback && callbacks.push(callback)                //如果是指定状态,那么使用微任务执行                if (state === requireState) {                    while (callbacks.length) {                        const cb = callbacks.shift()                        runMicroTask(() => cb(value)) // 使用微任务执行                    }                }            }            //resolve函数,改变状态为fulfilled            const resolve = (result) => {                //当且仅当状态是pending且未指定时进入                if (state === PENDING && !specified) {                    //如果传入的是当前Promise对象,那么直接reject                    if (result === this) {                        return reject(new TypeError('Chaining cycle detected for promise'))                    }                    specified = true;                    //如果result是Thenable,那么调用(ES6白皮书)                    //如果result是一个Promise,那么吸收它的状态                    try {                        if (result && isFunction(result.then)) {                            return runMicroTask(() => {                                try {                                    const res = r => (specified = false, resolve(r)) //临时打开                                    const rej = r => (specified = false, reject(r))  //临时打开                                                                result.then(res, rej)                                } catch (error) {                                    reject(error)                                }                            })                        }                    } catch (error) {                        return reject(error) //如果result.then抛出异常,那么直接reject                    }                    [state, value] = [FULFILLED, result]                    //fulfilled状态的回调函数,将其添加到onFulfilledCallbacks数组中,判断是否执行回调函数                    runOrQueueTasks(onFulfilledCallbacks, FULFILLED)                }            }            //reject函数,改变状态为rejected            const reject = (reason) => {                //当且仅当状态是pending且未指定时进入                if (state === PENDING && !specified) {                    [state, value, specified] = [REJECTED, reason, true]                    //rejected状态的回调函数,将其添加到onRejectedCallbacks数组中,判断是否执行回调函数                    runOrQueueTasks(onRejectedCallbacks, REJECTED)                }            }            //Promise状态处理过程            const promiseResolutionProcedure = (promise, x, resolve, reject) => {                // promise和x不能引用同一个对象                if (promise === x) {                    throw new TypeError('Chaining cycle detected for promise')                }                //如果x是一个Promise,那么promise对象直接吸收x的状态                if (isPromise(x)) { //这里兼容一下原生Promise                    //这里ES6白皮书是放到微队列中执行的(PromiseA+规范没有确定)                    return runMicroTask(() => x.then(resolve, reject))                }                //如果x是对象或者函数                if (isObject(x) || isFunction(x)) {                    let ignoreCall = false                    try {                        //取then方法报错,那么直接reject                        let then = x.then                        //如果then是一个函数,那么调用then方法                        if (isFunction(then)) {                            //调用采用x作为this,并传入两个参数resolve和reject,并要求resolve和reject只能调用一次                             return runMicroTask(() => then.call(x, y => {                                ignoreCall = ignoreCall || !promiseResolutionProcedure(promise, y, resolve, reject)                            }, r => {                                ignoreCall = ignoreCall || !reject(r)                            }))                        }                    } catch (error) {                        //如果then方法已经调用了resolve或reject,那么直接忽略                        ignoreCall || reject(error)                    }                }                //如果x不是一个对象或者函数,那么直接resolve                resolve(x)            }            //then方法            this.then = (onFulfilled, onRejected) => {                const promise = new (this.constructor[Symbol.species] || MyPromise)((resolve, reject) => {                    //如果onFulfilled是函数则调用                    state !== REJECTED && runOrQueueTasks(onFulfilledCallbacks, FULFILLED, isFunction(onFulfilled) ? value => {                        try {                            const x = onFulfilled(value)                            //根据函数返回结果进行Promise Resolution Procedure过程                            promiseResolutionProcedure(promise, x, resolve, reject)                        } catch (error) {                            reject(error)                        }                    } : resolve)//否则根据当前状态直接resolve                    //如果onRejected是函数则调用                    state !== FULFILLED && runOrQueueTasks(onRejectedCallbacks, REJECTED, isFunction(onRejected) ? value => {                        try {                            const x = onRejected(value)                            //根据函数返回结果进行Promise Resolution Procedure过程                            promiseResolutionProcedure(promise, x, resolve, reject)                        } catch (error) {                            reject(error)                        }                    } : reject)//否则根据当前状态直接reject                })                return promise            }            try {                executor(resolve, reject)            } catch (error) {                reject(error) //如果executor抛出异常,那么直接reject            }        }        //以下是ES6白皮书的拓展,不是Promise A+规范的内容        catch(onRejected) {            return this.then(null, onRejected)        }        finally(onFinally) {            //onFinally是一个不接收任何参数的函数            //如果 onFinally 抛出错误或返回被拒绝的 promise,则新的 promise 将使用该值进行拒绝            const onThen = isFunction(onFinally) ? () => {                const result = onFinally()                if (isPromise(result)) {                    return result.then(() => this, () => result)                }                return this;            } : onFinally            return this.then(onThen, onThen)        }        static resolve(value) {            //如果value是一个Promise,那么直接返回            if (isPromise(value)) {                return value            }            //使用call(this)用以支持非Promise构造器(ES6白皮书)            const { promise, resolve } = MyPromise.withResolvers.call(this)            resolve(value) //直接resolve            return promise        }        static reject(reason) {            //使用call(this)用以支持非Promise构造器(ES6白皮书)            const { promise, reject } = MyPromise.withResolvers.call(this)            reject(reason) //直接reject            return promise        }        static all(promises) {            promises = [...promises]            const { promise, resolve, reject } = MyPromise.withResolvers()            const results = []            //如果是空数组,那么直接返回一个resolved的Promise            if (!promises.length) {                resolve(results)            } else {                promises.forEach((p, i) => {                    MyPromise.resolve(p).then(value => {                        results[i] = value                        promises.pop() //每执行完成就弹出一个进行计数                        //如果全部已经是fulfilled状态,那么resolve结果                        promises.length || resolve(results)                    }, reject)                })            }            return promise        }        static race(promises) {            promises = [...promises]            const { promise, resolve, reject } = MyPromise.withResolvers()            //只要有一个是fulfilled或者rejected,那么当前Promise就需要改变状态            promises.forEach(p => MyPromise.resolve(p).then(resolve, reject))            return promise        }        static allSettled(promises) {            promises = [...promises]            const { promise, resolve } = MyPromise.withResolvers()            const results = []            //如果是空数组,那么直接返回一个resolved的Promise            if (!promises.length) {                resolve(results)            } else {                promises.forEach((p, i) => {                    MyPromise.resolve(p).then(value => {                        results[i] = { status: FULFILLED, value }                        promises.pop() //每执行完成就弹出一个进行计数                        //全部Promise已经是fulfilled或者rejected状态了,那么resolve                        promises.length || resolve(results)                    }, reason => {                        results[i] = { status: REJECTED, reason }                        promises.pop() //每执行完成就弹出一个进行计数                        //全部Promise已经是fulfilled或者rejected状态了,那么resolve                        promises.length || resolve(results)                    })                })            }            return promise        }        static any(promises) {            promises = [...promises]            const { promise, resolve, reject } = MyPromise.withResolvers()            const errors = []            //如果是空数组,那么直接返回一个rejected的Promise            if (!promises.length) {                reject(new AggregateError(errors, 'All promises were rejected'))            } else {                promises.forEach((p, i) => {                    MyPromise.resolve(p).then(resolve, reason => {                        errors[i] = reason                        promises.pop() //每执行完成就弹出一个进行计数                        //如果有rejected,那么收集所有rejected并最后全局reject                        promises.length || reject(new AggregateError(errors, 'All promises were rejected'))                    })                })            }            return promise        }        static try(fn, ...args) {            //使用call(this)用以支持非Promise构造器(ES6白皮书)            const { promise, resolve, reject } = MyPromise.withResolvers.call(this)            try {                const result = fn(...args)                resolve(result)            } catch (error) {                reject(error)            }            return promise        }        static withResolvers() {            let resolve, reject            const promise = new this((res, rej) => {                resolve = res                reject = rej            })            return { promise, resolve, reject }        }        static get [Symbol.species]() {            return MyPromise        }        [Symbol.toStringTag]() {            return "MyPromise"        }    }
复制代码
  验证
   我们主要在浏览器环境下验证,我们可以尝试几个例子,把Promise换成我们自定义的MyPromise,结果是一样的:
  例子一
  1.     Promise.resolve()
  2.         .then(() => {
  3.             console.log(0)
  4.             return Promise.resolve(4)
  5.         })
  6.         .then(res => {
  7.             console.log(res)
  8.         })
  9.     Promise.resolve()
  10.         .then(() => {
  11.             console.log(1);
  12.         })
  13.         .then(() => {
  14.             console.log(2);
  15.         })
  16.         .then(() => {
  17.             console.log(3);
  18.         })
  19.         .then(() => {
  20.             console.log(5);
  21.         })
  22.         .then(() => {
  23.             console.log(6);
  24.         })
复制代码
  例子二
  1.     new Promise(function(resolve, reject) {
  2.       console.log(1);
  3.       resolve();
  4.       console.log(2);
  5.     }).then(function() {
  6.       console.log(4);
  7.     });
  8.     setTimeout(()=>console.log(5))
  9.     console.log(3);
复制代码
  例子三
  1.     const first = () => (new Promise((resolve, reject) => {
  2.         console.log(1);
  3.         let p = new Promise((resolve, reject) => {
  4.             console.log(2);
  5.             setTimeout(() => {
  6.                 console.log(6);
  7.                 resolve(7);
  8.             }, 0)
  9.             resolve(4);
  10.         })
  11.         resolve(5);
  12.         p.then((arg) => {
  13.             console.log(arg);
  14.         });
  15.     }));
  16.     first().then((arg) => {
  17.         console.log(arg);
  18.     });
  19.     console.log(3);
复制代码
  总结
  以上实现是个人总结,模拟Promise的实现过程,基于ES6的实现,如果有什么错误,欢迎指出!
 

来源:豆瓜网用户自行投稿发布,如果侵权,请联系站长删除

相关推荐

您需要登录后才可以回帖 登录 | 立即注册