自己实现一个Promise库
-
先看基本使用
const promise = new Promise((resolve, reject) => { resolve(value) // or reject(reason) })
创建Promise时传入的回调函数是立即执行的,所以我们的Promise应该是这样(用ts实现)
function BDuckPromise(fn: (resolve: (value: any) => void, reject: (reason: any) => void) => any) { function resolve(value: any) { } function reject(reason: any) { } fn(resolve, reject); }
-
每个Promise对象都有三种生命状态:PENDING(未开始)、FULFILLED(已完成)、REJECTED(已失败)。生命状态只能是PENDING => FULFILLED 或者 PENDING => REJECTED 且一旦发生改变不可逆转。此时我们的代码是这样,具有了状态。
enum STATE { PENDING = 0, FULFILLED = 1, REJECTED = 2 } function BDuckPromise(fn: (resolve:(value: any) => void, reject: (reason: any) => void) => any) { let store = null, state = STATE.PENDING function resolve(value: any): void { store = value; state = STATE.FULFILLED; } function reject(reason: any): void { store = reason; state = STATE.REJECTED; } fn(resolve, reject) }
-
一个Promise对象回调中传入的值(value)或者拒因(reason)是在该示例对象的then函数中获取的
promise.then(value => { console.log(value); return value + 1 }, reason => { // .... })
then具有两个回调函数onfulfilled(用于成功时传递value)、onrejected(用于失败时传递reason)
所以我们then方法大概是长这样子
function BDuckPromise() { this.then = (onfulfilled, onrejected) => { if(state === STATE.PENDING) { return } if(state === STATE.FULFILLED) { onfulfilled(store) return } if(state === STATE.REJECTED) { onrejected(store) return } } }
但是等一下,如果我们写成这个样子当我们调用then的时候就必须要求promise的状态已经发生过改变我们才能获取到value或者reason,这个显然不是我们需要的。但是我们应该要写成什么样呢?分析一下
当我们调用then时候promise仍然处于pending状态时,我们应该怎么将value或者reason在它状态发生改变是传递出去呢?
显然,我们应该在状态发生改变时调用对应的onfulfilled或者onrejected回调。
那么我们就应该在状态为pending时将回调函数都存储起来,一旦状态改变了,就调用这些回调函数,这下就清楚了,应当在resolve或者reject中调用我们的onfulfilled或者onrejected回调
enum STATE { PENDING = 0, FULFILLED = 1, REJECTED = 2 } function BDuckPromise(fn: (resolve:(value: any) => void, reject: (reason: any) => void) => any) { let store = null, state = STATE.PENDING, callbacks = []; function resolve(value: any): void { store = value; state = STATE.FULFILLED; callbacks.forEach(callback => { if(callback.onfulfilled && 'function' === typeof callback.onfulfilled) { callback.onfulfilled(store) } }); callbacks = null }; function reject(reason: any): void { store = reason; state = STATE.REJECTED; callbacks.forEach(callback => { if(callback.onrejected && 'function' === typeof callback.onrejected) { callback.onrejected(store) } }); callbacks = null }; this.then = (onfulfilled, onrejected) => { if(state === STATE.PENDING) { callbacks.push({ onfulfilled, onrejected }) return } if(state === STATE.FULFILLED) { onfulfilled(store) return } if(state === STATE.REJECTED) { onrejected(store) return } }; fn(resolve, reject) }
-
then函数是有返回值的,且返回的的是一个新的Promise对象,所以还得改=_=!
const promise1 = new Promise((resolve, reject) => { resolve(1) }) // promise2 是一个新的Promise对象 const promise2 = promise1.then(value => { return value + 1 })
现在改成这样子
this.then = (onfulfilled, onrejected) => { return new BDuckPromise((_resolve, _reject) => { if(state === STATE.PENDING) { callbacks.push({ onfulfilled, onrejected }) return } if(state === STATE.FULFILLED) { onfulfilled(store) return } if(state === STATE.REJECTED) { onrejected(store) return } }); }
-
上一个then函数中return的值会传递给下一个then中作为值
const promise1 = new Promise((resolve, reject) => { resolve(1) }) // promise2 是一个新的Promise对象 const promise2 = promise1.then(value => { return value + 1 }) .then(value => { console.log(value) // 2 })
好吧,接着改=_=
this.then = (onfulfilled, onrejected) => { return new BDuckPromise((_resolve, _reject) => { if(state === STATE.PENDING) { callbacks.push({ onfulfilled, onrejected, _resolve, _reject }) return } if(state === STATE.FULFILLED) { const ret = onfulfilled(store) _resolve(ret) return } if(state === STATE.REJECTED) { const ret = onrejected(store) _reject(ret) return } }); } // 相应的resolve, reject也做相应的更改 function resolve(value: any): void { store = value; state = STATE.FULFILLED; callbacks.forEach(callback => { if(callback.onfulfilled && 'function' === typeof callback.onfulfilled) { const ret = callback.onfulfilled(store) callback._resolve(ret) } }) } function reject(reason: any): void { store = reason; state = STATE.REJECTED; callbacks.forEach(callback => { if(callback.onrejected && 'function' === typeof callback.onrejected) { const ret = callback.onrejected(store) callback._reject(ret) } }) }
-
如果then中return的是一个新的Promise则下一个then中的value或reason是这个返回的Promise中resolve或者reject中传递value或者reason
enum STATE { PENDING = 0, FULFILLED = 1, REJECTED = 2 } function BDuckPromise(fn: (resolve:(value: any) => void, reject: (reason: any) => void) => any) { let store:any = null, state = STATE.PENDING, callbacks:any = [] function resolve(value: any): void { setTimeout(() => { state = STATE.FULFILLED; // value 是一个Promise对象 if(value && 'object' === typeof value && value.then && 'function' === typeof value.then) { // do then value.then(resolve, reject) return } // value 不是Promise对象 store = value; callbacks.forEach(callback => { if(callback.onfulfilled && 'function' === typeof callback.onfulfilled) { const ret = callback.onfulfilled(store) callback._resolve(ret) } }) callbacks = [] }) } function reject(reason: any): void { setTimeout(() => { state = STATE.REJECTED; // value 是一个Promise对象 if(reason && 'object' === typeof reason && reason.then && 'function' === typeof reason.then) { reason.then(resolve, reject) return } // value 不是Promise对象 store = reason; callbacks.forEach(callback => { if(callback.onrejected && 'function' === typeof callback.onrejected) { const ret = callback.onrejected(store) callback._reject(ret) } }) callbacks = [] }, 0) } this.then = (onfulfilled, onrejected) => { return new BDuckPromise((_resolve, _reject) => { if(state === STATE.PENDING) { callbacks.push({ onfulfilled, onrejected, _resolve, _reject }) return } if(state === STATE.FULFILLED) { const ret = onfulfilled(store) _resolve(ret) return } if(state === STATE.REJECTED) { const ret = onrejected(store) _reject(ret) return } }); } fn(resolve, reject) } export default BDuckPromise;