状态机制
[[PromiseState]] 有三种状态,fulfilled
、rejected
、pending
。
初始值为pending
。
状态值一旦改变就不能再改变。
class MyPromise { static PENDING = 'pending' static FULFILLED = 'fulfilled' static REJECTED = 'rejected' constructor() { this.state = MyPromise.PENDING } }
MyPromise接受一个回调函数,回调函数接受两个方法,第一个是resolve
,第二个是reject
。resolve
、reject
都会接受一个表示结果原因的参数。
[[PromiseResult]]初始值为null。
class MyPromise { static PENDING = 'pending' static FULFILLED = 'fulfilled' static REJECTED = 'rejected' constructor(executor) { this.state = MyPromise.PENDING this.result = null // 结果 executor(this.resolve, this.reject) } resolve(result) { if (this.state === MyPromise.PENDING) { this.state = MyPromise.FULFILLED this.result = result } } reject(reason) { if (this.state === MyPromise.PENDING) { this.state = MyPromise.REJECTED this.result = reason } } }
resolve
、reject
被作为回调参数传入executor
调用时this绑定会隐性丢失,因为我们知道函数中的this最终会指向调用此函数时的对象。
在严格模式下是undefined,非严格模式下会指向window对象。
let p = new MyPromise((resolve, reject) => { // ... resolve('ok') // 调用时this绑定会隐性丢失 })
所以需要将它们的this绑定
class MyPromise { constructor(executor) { // ... executor(this.resolve.bind(this), this.reject.bind(this)) } }
如果executor执行出错,需要reject掉。
class MyPromise { static PENDING = 'pending' static FULFILLED = 'fulfilled' static REJECTED = 'rejected' constructor(executor) { this.state = MyPromise.PENDING this.result = null // 结果 try { executor(this.resolve.bind(this), this.reject.bind(this)) } catch (e) { this.reject(this.result) } } resolve(result) { if (this.state === MyPromise.PENDING) { this.state = MyPromise.FULFILLED this.result = result } } reject(reason) { if (this.state === MyPromise.PENDING) { this.state = MyPromise.REJECTED this.result = reason } } }
then方法实现
then
接受两个参数onFulFilled
,onRejected
。
then方法是异步执行的。规范中是用的微任务执行,但是JavaScript没有能直接操控微任务队列的方法,但是可以用宏任务setTimeout
代替。
then方法调用的时候状态可能有三种情况,也就是对应着状态机制中的三种状态,需要分别作处理。
class MyPromise { // ... then(onFulfilled, onRejected) { if (this.state === MyPromise.FULFILLED) { // 状态变为fulfilled时执行onFulfilled setTimeout(() => { onFulfilled(this.result) }) } else if (this.state === MyPromise.REJECTED) { // 状态变为fulfilled时执行onRejected setTimeout(() => { onRejected(this.result) }) } else { // ... } } }
当调用then方法resolve
,reject
还未执行,就是executor中执行了异步的操作,state的状态还为pending
时,我们需要让onFulfilled
,onRejected
回调在恰当的时机,即state状态变更为fulfilled
或rejected
时才执行。
也就是说then方法调用时状态为pending
的话,就要让onFulfilled
,onRejected
在resolve
,reject
方法调用的时候才去执行。
class MyPromise { constructor(executor) { // ... this.onFulfilledCallbacks = [] this.onRejectedCallbacks = [] } resolve(result) { if (this.state === MyPromise.PENDING) { this.state = MyPromise.FULFILLED this.result = result // 执行pending时传入的onFulfilled this.onFulfilledCallbacks.forEach(callback => { callback(result) }) } } reject(reason) { if (this.state === MyPromise.PENDING) { this.state = MyPromise.REJECTED this.result = reason // 执行pending时传入的onRejected this.onRejectedCallbacks.forEach(callback => { callback(reason) }) } } then(onFulfilled, onRejected) { if (this.state === MyPromise.FULFILLED) { // 状态变为fulfilled时执行onFulfilled setTimeout(() => { onFulfilled(this.result) }) } else if (this.state === MyPromise.REJECTED) { // 状态变为fulfilled时执行onRejected setTimeout(() => { onRejected(this.result) }) } else { // 将两个回调保存起来,等待恰当的时机调用 this.onFulfilledCallbacks.push(() => { setTimeout(() => { onFulfilled(this.result) }) }) this.onRejectedCallbacks.push(() => { setTimeout(() => { onRejected(this.result) }) }) } } }
2.2.7.1 If either onFulfilled or onRejected returns a value x, run the Promise Resolution Procedure [[Resolve]](promise2, x).
2.2.7.2 If either onFulfilled or onRejected throws an exception e, promise2 must be rejected with e as the reason.
2.2.7.3 If onFulfilled is not a function and promise1 is fulfilled, promise2 must be fulfilled with the same value as promise1.
2.2.7.4 If onRejected is not a function and promise1 is rejected, promise2 must be rejected with the same reason as promise1.
2.2.7.1 如果 onFulfilled 或者 onRejected 返回一个值 x ,则运行[[Resolve]](promise2, x)
2.2.7.2 如果 onFulfilled 或者 onRejected 抛出一个异常 e ,则 promise2 必须以 e 作为原因拒绝
2.2.7.3 如果 onFulfilled 不是函数且 promise1 成功执行, promise2 必须成功执行并返回相同的值
2.2.7.4 如果 onRejected 不是函数且 promise1 拒绝执行, promise2 必须拒绝执行并返回相同的据因
then链式调用
class MyPromise { constructor(executor) { // ... this.onFulfilledCallbacks = [] this.onRejectedCallbacks = [] } resolve(result) { if (this.state === MyPromise.PENDING) { this.state = MyPromise.FULFILLED this.result = result // 执行pending时传入的onFulfilled this.onFulfilledCallbacks.forEach(callback => { callback(result) }) } } reject(reason) { if (this.state === MyPromise.PENDING) { this.state = MyPromise.REJECTED this.result = reason // 执行pending时传入的onRejected this.onRejectedCallbacks.forEach(callback => { callback(reason) }) } } then(onFulfilled, onRejected) { if (this.state === MyPromise.FULFILLED) { // 状态变为fulfilled时执行onFulfilled setTimeout(() => { try { if (typeof onFulfilled !== 'function') { // 2.2.7.3 如果 onFulfilled 不是函数且 promise1 成功执行, promise2 必须成功执行并返回相同的值 resolve(this.result) } else { // 2.2.7.1 如果 onFulfilled 或者 onRejected 返回一个值 x ,则运行[[Resolve]](promise2, x) let x = onFulfilled(this.result) resolvePromise(promise2, x) } } catch (e) { // 2.2.7.2 如果 onFulfilled 或者 onRejected 抛出一个异常 e ,则 promise2 必须以 e 作为原因拒绝 reject(e) } }) } else if (this.state === MyPromise.REJECTED) { // 状态变为fulfilled时执行onRejected setTimeout(() => { try { if (typeof onRejected !== 'function') { // 2.2.7.4 如果 onRejected 不是函数且 promise1 拒绝执行, promise2 必须拒绝执行并返回相同的据因 reject(this.result) } else { // 2.2.7.1 如果 onFulfilled 或者 onRejected 返回一个值 x ,则运行[[Resolve]](promise2, x) let x = onRejected(this.result) resolvePromise(promise2, x) } } catch (e) { // 2.2.7.2 如果 onFulfilled 或者 onRejected 抛出一个异常 e ,则 promise2 必须以 e 作为原因拒绝 reject(e) } }); } else { // 将两个回调保存起来,等待恰当的时机调用 this.onFulfilledCallbacks.push(() => { setTimeout(() => { onFulfilled(this.result) }) }) this.onRejectedCallbacks.push(() => { setTimeout(() => { onRejected(this.result) }) }) } } }
接下来实现resolvePromise
根据规范的描述
function resolvePromise(promise, x) { // x等于promise抛出异常,为了防止无限循环 if (x === promise) { throw new TypeError('错啦') } // 如果x是一个promise,那就继续执行 if (x instanceof MyPromise) { x.then((y) => { resolvePromise(promise, y) }, (r) => { promise.reject(r) }) } else if (Object.prototype.toString.call(x) === '[object Object]' || typeof x === 'function') { // 如果是对象或者方法,为了兼容有then方法的类似promise的对象或方法 let then try { then = x.then } catch (e) { return promise.reject(e) } // 2.3.3.3 如果 then 是函数,将 x 作为函数的作用域 this 调用之。传递两个回调函数作为参数,第一个参数叫做 resolvePromise ,第二个参数叫做 rejectPromise if (typeof then === 'function') { let called = false // 2.3.3.3.1 如果 resolvePromise 以值 y 为参数被调用,则运行 [[Resolve]](promise, y) try { then.call( x, // 2.3.3.3.1 如果 resolvePromise 以值 y 为参数被调用,则运行 [[Resolve]](promise, y) y => { // 2.3.3.3.3 如果 resolvePromise 和 rejectPromise 均被调用,或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用 if (called) return called = true resolvePromise(promise, y) }, // 2.3.3.3.2 如果 rejectPromise 以据因 r 为参数被调用,则以据因 r 拒绝 promise r => { // 2.3.3.3.3 如果 resolvePromise 和 rejectPromise 均被调用,或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用 if (called) return called = true promise.reject(r) } ) } catch (e) { // 2.3.3.3.4 如果调用 then 方法抛出了异常 e // 2.3.3.3.4.1 如果 resolvePromise 或 rejectPromise 已经被调用,则忽略之 // 2.3.3.3.4.2 否则以 e 为据因拒绝 promise if (called) return called = true promise.reject(e) } } else { // 2.3.3.4 如果 then 不是函数,以 x 为参数执行 promise promise.resolve(x) } } else { // 2.3.3.4 如果 then 不是函数,以 x 为参数执行 promise promise.resolve(x) } }
最后优化一下then中的条件分支
最终版
class MyPromise { static PENDING = 'pending' static FULFILLED = 'fulfilled' static REJECTED = 'rejected' constructor(executor) { this.state = MyPromise.PENDING this.result = null this.onFulfilledCallbacks = [] this.onRejectedCallbacks = [] try { executor(this.resolve.bind(this), this.reject.bind(this)) } catch (e) { this.reject(this.result) } } resolve(result) { if (this.state === MyPromise.PENDING) { this.state = MyPromise.FULFILLED this.result = result this.onFulfilledCallbacks.forEach(callback => { callback(result) }) } } reject(reason) { if (this.state === MyPromise.PENDING) { this.state = MyPromise.REJECTED this.result = reason this.onRejectedCallbacks.forEach(callback => { callback(reason) }) } } then(onFulfilled, onRejected) { let promise2 = new MyPromise((resolve, reject) => { const handler = (fn, state) => { setTimeout(() => { try { // 2.2.7.3 如果 onFulfilled 不是函数且 promise1 成功执行, promise2 必须成功执行并返回相同的值 if (typeof fn !== 'function') { if (state === MyPromise.FULFILLED) { resolve(this.result) } else if (state === MyPromise.REJECTED) { reject(this.result) } } else { // 2.2.7.1 如果 onFulfilled 或者 onRejected 返回一个值 x ,则运行[[Resolve]](promise2, x) let x = fn(this.result) resolvePromise(promise2, x) } } catch (e) { // 2.2.7.2 如果 onFulfilled 或者 onRejected 抛出一个异常 e ,则 promise2 必须以 e 作为原因拒绝 reject(e) } }) } if (this.state === MyPromise.FULFILLED) { handler(onFulfilled, MyPromise.FULFILLED) } else if (this.state === MyPromise.REJECTED) { handler(onRejected, MyPromise.REJECTED) } else { this.onFulfilledCallbacks.push(() => { handler(onFulfilled, MyPromise.FULFILLED) }) this.onRejectedCallbacks.push(() => { handler(onRejected, MyPromise.REJECTED) }) } }) return promise2 } } function resolvePromise(promise, x) { // x等于promise抛出异常,为了防止无限循环 if (x === promise) { throw new TypeError('错啦') } // 如果x是一个promise,那就继续执行 if (x instanceof MyPromise) { x.then((y) => { resolvePromise(promise, y) }, (r) => { promise.reject(r) }) } else if (Object.prototype.toString.call(x) === '[object Object]' || typeof x === 'function') { // 如果是对象或者方法,为了兼容有then方法的类似promise的对象或方法 let then try { then = x.then } catch (e) { return promise.reject(e) } // 2.3.3.3 如果 then 是函数,将 x 作为函数的作用域 this 调用之。传递两个回调函数作为参数,第一个参数叫做 resolvePromise ,第二个参数叫做 rejectPromise if (typeof then === 'function') { let called = false // 2.3.3.3.1 如果 resolvePromise 以值 y 为参数被调用,则运行 [[Resolve]](promise, y) try { then.call( x, // 2.3.3.3.1 如果 resolvePromise 以值 y 为参数被调用,则运行 [[Resolve]](promise, y) y => { // 2.3.3.3.3 如果 resolvePromise 和 rejectPromise 均被调用,或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用 if (called) return called = true resolvePromise(promise, y) }, // 2.3.3.3.2 如果 rejectPromise 以据因 r 为参数被调用,则以据因 r 拒绝 promise r => { // 2.3.3.3.3 如果 resolvePromise 和 rejectPromise 均被调用,或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用 if (called) return called = true promise.reject(r) } ) } catch (e) { // 2.3.3.3.4 如果调用 then 方法抛出了异常 e // 2.3.3.3.4.1 如果 resolvePromise 或 rejectPromise 已经被调用,则忽略之 // 2.3.3.3.4.2 否则以 e 为据因拒绝 promise if (called) return called = true promise.reject(e) } } else { // 2.3.3.4 如果 then 不是函数,以 x 为参数执行 promise promise.resolve(x) } } else { // 2.3.3.4 如果 then 不是函数,以 x 为参数执行 promise promise.resolve(x) } }
catch
catch就是then(null, noReject)的语法糖。
class MyPromise { // ... catch(onReject) { return this.then(null, onReject) } }
finally
finally不管状态如何都会执行也不会接受任何值。
class MyPromise { // ... finally(onFinally) { return this.then((result) => { // 回调里返回的是Promise需要等待 return MyPromise.resolve(onFinally()).then(() => result) }, (reason) => { return MyPromise.resolve(onFinally()).then(() => reason) }) } }
Promise.all
Promise.all
接受一个可迭代对象,当所有promise的状态都变为fulfilled时,才改变自身状态为fulfilled并返回一个传入的迭代对象的值的数组。
class MyPromise { // ... static all(promiseAry) { let promiseIns = new MyPromise((resolve, reject) => { let _pAryLen = promiseAry.length, // 迭代对象 _pAry = Array.from(promiseAry), // 结果 _pAryResults = new Array(_pAryLen), _isResolveAll = (() => { let count = 0 return () => _pAryLen === ++count })(), _c = (r, i) => { // 保持值的位置顺序一致 _pAryResults[i] = r _isResolveAll() && resolve(_pAryResults) }, _f = (e) => { reject(e) }; _pAry.forEach((p, i) => { p.then((r) => _c(r, i)).catch(_f) }) }) return promiseIns } }
Promise.race
Promise.race
接受一个可迭代对象,当其中一个promise的状态变为fulfilled时,才改变自身状态为fulfilled并返回这个对象的值。
class MyPromise { // ... static race(promiseAry) { let promiseIns = new MyPromise((resolve, reject) => { let _pAry = Array.from(promiseAry) _pAry.forEach(p => { p.then((r => { resolve(r) })).catch(e => { reject(e) }) }) }) return promiseIns } }
0