做者:@gauseen前端
Promises/A+
规范可在这里查看git
promise
有 3
个状态,分别为 pending
, fulfilled
和 rejected
github
promise 在 pending
状态promise
fulfilled
或 rejected
状态promise 在 fulfilled
状态异步
promise 在 rejected
状态函数
// promise 三种状态 const PENDING = 'pending' const FULFILLED = 'fulfilled' const REJECTED = 'rejected' // MyPromise 构造函数 function MyPromise (fn) { // 初始化状态 this.state = PENDING this.result = void 0 this.handlerQueue = [] let resolve = (value) => { transitionState(this, FULFILLED, value) } let reject = (reason) => { transitionState(this, REJECTED, reason) } // 调用 Promise 构造函数回调 try { fn(resolve, reject) } catch (error) { reject(error) } }
状态迁移方法,即调用了 fn(resolve, reject)
中的 resolve, reject
方法后,须要改变 promise
状态:this
pending --> fulfilled
spa
pending --> rejected
prototype
function transitionState (promise, state, result) { if (promise.state !== PENDING) return promise.state = state promise.result = result // 这里先占个坑位 }
then
方法返回的是一个新的 Promise
实例(注意:不是原来那个 Promise
实例),只有这样才能不断的链式调用,依次改变状态code
MyPromise.prototype.then = function (onFulfilled, onRejected) { return new MyPromise((resolve, reject) => { let handler = { onFulfilled, onRejected, resolve, reject } // 若当前状态为 pending 则将其放在 handlerQueue 队列中,等待 resolve 或 reject 方法改变其状态 // 不然直接调用 then 方法中的 resolve 或 reject 回调函数 if (this.state ==== PENDING) { this.handlerQueue.push(handler) } else { dispatchHandler(handler, this.state, this.result) } }) }
const isFunction = arg => typeof arg === 'function' function dispatchHandler (handler, state, result) { let { onFulfilled, onRejected, resolve, reject } = handler if (state === FULFILLED) { let finalValue = isFunction(onFulfilled) ? onFulfilled(result) : result resolve(finalValue) } else if (state === REJECTED) { let finalReason = isFunction(onRejected) ? onRejected(result) : result reject(finalReason) } }
以上代码,只支持 Promise 回调函数参数 resolve
和 reject
同步调用的状况,以下示例代码:
// 支持 let myPromise = new MyPromise((resolve, reject) => { // resolve 同步调用 resolve('同步调用 value') }) myPromise.then((value) => { console.log('value: ', value) }, (reason) => { console.log('reason: ', reason) })
可是,使用异步调用不支持,以下示例代码:
// 暂不支持 let myPromise = new MyPromise((resolve, reject) => { // resolve 异步调用 setTimeout(() => { resolve('异步调用 value') }) }) myPromise.then((value) => { console.log('value: ', value) }, (reason) => { console.log('reason: ', reason) })
之因此不支持异步调用 resolve 或 reject
,是由于 then
方法中以下代码片断:
// 当 resolve 为异步调用,then 方法执行时,promise 状态为 pending。 // 因此 then 回调函数 onFulfilled 和 onRejected 在 handlerQueue 队列里,没有被调用 if (this.state ==== PENDING) { this.handlerQueue.push(handler) } else { // ... }
为支持 resolve
、reject
异步调用,状态迁移方法 transitionState
,作以下修改:
function transitionState (promise, state, result) { if (promise.state !== PENDING) return promise.state = state promise.result = result // 新增代码开始 promise.handlerQueue.forEach(handler => { dispatchHandler(handler, state, result) }) // 新增代码结束 }
由于 catch
方法是 .then(null, onRejected)
的别名,因此实现 catch
代码以下:
MyPromise.prototype.catch = function (onRejected) { return this.then(null, onRejected) }
如上,简单实现了 promise
,支持链式调用 then 和 catch
欢迎关注无广告文章公众号:学前端