况雪柳 发表于 2025-7-6 16:02:05

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

   本文基于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:  
    Promise是一个具有then方法的对象或者函数,这个then方法需要满足后面的一些规范。
    Thenable是一个具有then方法的对象或者函数。  从上面的术语可以看到,Promise是Thenable,但是Thenable不一定是Promise,主要区别有两点:
  1. Promise对象具有三个状态:pending, fulfilled, rejected  
    1、当状态是pending时,Promise的状态可以变为fulfilled或者rejected。
    2、当状态是fulfilled时,Promise的状态不可再改变,并具有一个不可改变的结果,结果可以是null、undefined、对象、函数、Promise或者Thenable等。
    3、当状态是rejected时,Promise的状态不可再改变,并可具有一个不可改变的原因,原因可以是null、undefined、对象、函数、Promise或者Thenable等。   2. Promise对象需要提供一个then方法,这个then方法需要接收两个参数:   
    promise.then(onFulfilled, onRejected)
   
    //onFulfilled是当promise状态从pending变为fulfilled后需要执行的函数
    //onRejected是当promise状态从pending变为rejected后需要执行的函数  而在ES6的规范中,Promise不仅满足上面Promises/A+规范,还有其他一些特性来保证Promise的实用性,比如ES6中,Promise的构造函数需要传入一个executor函数参数,它接收两个函数作为参数:resolveFunc 和 rejectFunc,分别表示将Promise的状态置为fulfilled还是rejected,因此,我们可以写出Promise的构造函数大概是这个样子的:
    class MyPromise {
      constructor(executor) {
            //表示状态是否已指定,保证状态只会被改变一次
            let specified = false
            //状态
            let state = PENDING
            //结果或者原因
            let value = void 0

            //fulfilled状态的回调函数
            let onFulfilledCallbacks = []
            //rejected状态的回调函数
            let onRejectedCallbacks = []

            //resolve函数,改变状态为fulfilled
            const resolve = (result) => { }
            //reject函数,改变状态为rejected
            const reject = (reason) => { }

            //then方法
            this.then = (onFulfilled, onRejected) => { }

            try {
                executor(resolve, reject)
            } catch (error) {
                reject(error) //如果executor抛出异常,那么直接reject
            }
      }
    }  上面只是Promise大致的样子,接下来我们就需要去实现这几个函数即可:resolve、reject、then方法
  首先,我们需要先定义一些通用的函数与变量:  
    //Promise的三个状态
    const PENDING = 'pending'
    const FULFILLED = 'fulfilled'
    const REJECTED = 'rejected'
    //判断一个值是否是一个函数
    const isFunction = value => value && typeof value === 'function' && value instanceof Function
    //判断一个值是否是一个Promise
    const isPromise = value => value && (value instanceof MyPromise || value instanceof Promise)
    //判断一个值是否是一个对象
    const isObject = value => value && typeof value === 'object' && value instanceof Object
    //执行微任务,没有返回结果
    function runMicroTask(fn) {
      //首先看微任务队列函数是否存在,如果存在则使用微任务队列执行
      if (isFunction(queueMicrotask)) {
            runMicroTask = f => queueMicrotask(f)
      } else if (isObject(process) && isFunction(process.nextTick)) { //如果是Node.js环境
            runMicroTask = f => process.nextTick(f)
      } else if (isFunction(MutationObserver)) { //如果是浏览器环境
            runMicroTask = f => {
                const observer = new MutationObserver(f)
                const node = document.createTextNode('')
                observer.observe(node, { characterData: true })
                node.data = '1' //触发MutationObserver
            }
      } else { //如果都不存在,那么使用setTimeout(fn, 0)执行
            runMicroTask = f => setTimeout(f, 0)
      }
      runMicroTask(fn)
    }  reject函数
  reject函数的视线很简单,就是变更Promise的状态和结果即可,结果往往是一个Error对象:  
    //reject函数,改变状态为rejected
    const reject = (reason) => {
      //当且仅当状态是pending且未指定时进入
      if (state === PENDING && !specified) {
             =

            //rejected状态的回调函数,将其添加到onRejectedCallbacks数组中,判断是否执行回调函数
            runOrQueueTasks(onRejectedCallbacks, REJECTED)
      }
    }  这里runOrQueueTasks其实就是将回调函数放到微任务里并准备执行回调函数,实现如下:  
    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函数
  resolve的函数实现逻辑更多一些,具体可以看看MDN的说明(跳转),总结下来就是:  
    1、resolve函数接收一个结果对象result
    2、如果result结果对象是当前Promise自身,那么将会reject一个TypeError
    3、如果result结果对象不是一个Thenable对象,那么Promise将会被立即FULFILLED,并采用这个result作为结果
    4、如果result结果对象是一个Thenable对象,那么将会把Thenable对象的then方法放到微任务去执行,并Promise的resolve和reject作为then方法的两个参数传进入(近似可以这么认为),就是说Promise的结果又Thenable决定  因此我们的resolve函数大概是这个样子的:  
    //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
            }

             =

            //fulfilled状态的回调函数,将其添加到onFulfilledCallbacks数组中,判断是否执行回调函数
            runOrQueueTasks(onFulfilledCallbacks, FULFILLED)
      }
    }  then方法 
  根据Promises/A+规范,then方法需要满足下面的:  
    1、调用方式:promise.then(onFulfilled, onRejected),这里onFulfilled、onRejected都必须是函数,否则将被忽略
    2、onFulfilled、onRejected需要分别在promise变为fulfilled和rejected后执行,将结果或者原因作为第一个参数传入,并且至多执行一次
    3、onFulfilled、onRejected不能在当前上下文中执行,需要放到setTimeout、微任务这样的上下文去执行
    4、then方法如果调用多次,onFulfilled和onRejected需要按他们所在的then方法的调用顺序依次执行
    5、then方法方法需要返回一个新的Promise对象:promise2 = promise1.then(onFulfilled, onRejected)
      1、如果onFulfilled和onRejected返回一个值x,那么将执行Promise Resolution Procedure,将promise2和x作为参数传入
      2、如果onFulfilled或者onRejected抛出异常,那么promise2将会使用这个异常进行reject
      3、如果onFulfilled不是函数且promise1状态是fulfilled,或者onRejected不是函数且promise1状态是rejected,那么promise2将会吸收promise1的状态,即promise1和promise2保持相同的结果和状态   因为then方法的实现大致如下
    //then方法
    this.then = (onFulfilled, onRejected) => {
      const promise = new (this.constructor || 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
    }   这里说下Promise Resolution Procedure过程
    Promise Resolution Procedure过程采用这个表达方式:[](promise, x),其实可以理解为就是个函数处理过程,表示promise怎么去根据x的值变更状态
    1、如果promise和x是相同的对象,那么promise将会被reject(TypeError)
    2、如果x是一个Promise,那么promise对象将会吸收x的状态,即promise和x保持相同的结果和状态
    3、如果x是一个Thenable,那么调用Thenable的then方法,并将promise的resolve和reject函数作为参数传入then方法调用
      1、如果resolve函数被调用,并接收到结果y,那么接着执行Promise Resolution Procedure过程:[](promise, y)
      2、如果reject函数被调用,那么接收到结果r,那么promise将会被reject(r)
      3、resolve和reject函数只能被调用一次
      4、如果then方法调用报错,且resolve和reject函数都未被调用,那么promise将会被reject
    4、否则promise将会被resolve(x)  大致的实现代码是这个样子的:  
    //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方法的实现是参考Promises/A+规范,MDN上的描述大致含义和这个差不多,感兴趣的可以去看看(跳转)
  到这里我们的Promise就已经实现了,接下来说说Promise其它方法的拓展,这部分不是Promises/A+规范的内容,是ES6的Promise的拓展
  catch函数
  catch函数可以参考MDN上面的说明(跳转),而我们的实现如下:  
    class MyPromise {
      //...其它代码
      
      //以下是ES6白皮书的拓展,不是Promise A+规范的内容
      catch(onRejected) {
            return this.then(null, onRejected)
      }
    }  finally函数
  finally函数可以参考MDN上面的说明(跳转),而我们的实现如下:
    class MyPromise {
      //...其它代码
      
      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)
      }
    }  resolve函数
  resolve函数可以参考MDN上面的说明(跳转),而我们的实现如下:  
    class MyPromise {
      //...其它代码
      
      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
      }
    }  reject函数
  reject函数可以参考MDN上面的说明(跳转),而我们的实现如下: 
    class MyPromise {
      //...其它代码
      
      static reject(reason) {
            //使用call(this)用以支持非Promise构造器(ES6白皮书)
            const { promise, reject } = MyPromise.withResolvers.call(this)
            reject(reason) //直接reject
            return promise
      }
    }  all函数
  all函数可以参考MDN上面的说明(跳转),而我们的实现如下: 
    class MyPromise {
      //...其它代码
      
      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 = value
                        promises.pop() //每执行完成就弹出一个进行计数
                        //如果全部已经是fulfilled状态,那么resolve结果
                        promises.length || resolve(results)
                  }, reject)
                })
            }
            return promise
      }
    }  race函数
  race函数可以参考MDN上面的说明(跳转),而我们的实现如下:
    class MyPromise {
      //...其它代码
      
      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
      }
    }  allSettled函数
  allSettled函数可以参考MDN上面的说明(跳转),而我们的实现如下:
    class MyPromise {
      //...其它代码
      
      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 = { status: FULFILLED, value }
                        promises.pop() //每执行完成就弹出一个进行计数
                        //全部Promise已经是fulfilled或者rejected状态了,那么resolve
                        promises.length || resolve(results)
                  }, reason => {
                        results = { status: REJECTED, reason }
                        promises.pop() //每执行完成就弹出一个进行计数
                        //全部Promise已经是fulfilled或者rejected状态了,那么resolve
                        promises.length || resolve(results)
                  })
                })
            }
            return promise
      }
    }  any函数
  any函数可以参考MDN上面的说明(跳转),而我们的实现如下:
    class MyPromise {
      //...其它代码
      
      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 = reason
                        promises.pop() //每执行完成就弹出一个进行计数
                        //如果有rejected,那么收集所有rejected并最后全局reject
                        promises.length || reject(new AggregateError(errors, 'All promises were rejected'))
                  })
                })
            }
            return promise
      }
    }  try函数
  try函数可以参考MDN上面的说明(跳转),而我们的实现如下:  
    class MyPromise {
      //...其它代码
      
      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
      }
    }  withResolvers函数
  withResolvers函数可以参考MDN上面的说明(跳转),而我们的实现如下:
    class MyPromise {
      //...其它代码
      
      static withResolvers() {
            let resolve, reject
            const promise = new this((res, rej) => {
                resolve = res
                reject = rej
            })
            return { promise, resolve, reject }
      }
    }  最后附上自己实现的Promise完整代码:
查看代码    //Promise的三个状态
    const PENDING = 'pending'
    const FULFILLED = 'fulfilled'
    const REJECTED = 'rejected'
    //判断一个值是否是一个函数
    const isFunction = value => value && typeof value === 'function' && value instanceof Function
    //判断一个值是否是一个Promise
    const isPromise = value => value && (value instanceof MyPromise || value instanceof Promise)
    //判断一个值是否是一个对象
    const isObject = value => value && typeof value === 'object' && value instanceof Object
    //执行微任务,没有返回结果
    function runMicroTask(fn) {
      //首先看微任务队列函数是否存在,如果存在则使用微任务队列执行
      if (isFunction(queueMicrotask)) {
            runMicroTask = f => queueMicrotask(f)
      } else if (isObject(process) && isFunction(process.nextTick)) { //如果是Node.js环境
            runMicroTask = f => process.nextTick(f)
      } else if (isFunction(MutationObserver)) { //如果是浏览器环境
            runMicroTask = f => {
                const observer = new MutationObserver(f)
                const node = document.createTextNode('')
                observer.observe(node, { characterData: true })
                node.data = '1' //触发MutationObserver
            }
      } else { //如果都不存在,那么使用setTimeout(fn, 0)执行
            runMicroTask = f => setTimeout(f, 0)
      }
      runMicroTask(fn)
    }    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                  }                   =                   //fulfilled状态的回调函数,将其添加到onFulfilledCallbacks数组中,判断是否执行回调函数                  runOrQueueTasks(onFulfilledCallbacks, FULFILLED)                }            }            //reject函数,改变状态为rejected            const reject = (reason) => {                //当且仅当状态是pending且未指定时进入                if (state === PENDING && !specified) {                   =                   //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 || 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 = 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 = { status: FULFILLED, value }                        promises.pop() //每执行完成就弹出一个进行计数                        //全部Promise已经是fulfilled或者rejected状态了,那么resolve                        promises.length || resolve(results)                  }, reason => {                        results = { 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 = 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 () {            return MyPromise      }      () {            return "MyPromise"      }    }  验证
   我们主要在浏览器环境下验证,我们可以尝试几个例子,把Promise换成我们自定义的MyPromise,结果是一样的:
  例子一
    Promise.resolve()
      .then(() => {
            console.log(0)
            return Promise.resolve(4)
      })
      .then(res => {
            console.log(res)
      })
    Promise.resolve()
      .then(() => {
            console.log(1);
      })
      .then(() => {
            console.log(2);
      })
      .then(() => {
            console.log(3);
      })
      .then(() => {
            console.log(5);
      })
      .then(() => {
            console.log(6);
      })  例子二
    new Promise(function(resolve, reject) {
      console.log(1);
      resolve();
      console.log(2);
    }).then(function() {
      console.log(4);
    });
    setTimeout(()=>console.log(5))
    console.log(3);  例子三
    const first = () => (new Promise((resolve, reject) => {
      console.log(1);
      let p = new Promise((resolve, reject) => {
            console.log(2);
            setTimeout(() => {
                console.log(6);
                resolve(7);
            }, 0)
            resolve(4);
      })
      resolve(5);
      p.then((arg) => {
            console.log(arg);
      });

    }));

    first().then((arg) => {
      console.log(arg);
    });
    console.log(3);  总结
  以上实现是个人总结,模拟Promise的实现过程,基于ES6的实现,如果有什么错误,欢迎指出!
 

来源:豆瓜网用户自行投稿发布,如果侵权,请联系站长删除
页: [1]
查看完整版本: JS基于Promises/A+规范实现一个Promise