本文基于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) {
- [state, value, specified] = [REJECTED, reason, true]
- //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
- }
- [state, value] = [FULFILLED, result]
- //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[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
- }
复制代码 这里说下Promise Resolution Procedure过程- Promise Resolution Procedure过程采用这个表达方式:[[Resolve]](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过程:[[Resolve]](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[i] = 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[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
- }
- }
复制代码 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[i] = 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 } [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,结果是一样的:
例子一- 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的实现,如果有什么错误,欢迎指出!
来源:豆瓜网用户自行投稿发布,如果侵权,请联系站长删除 |