手動實現一個Promise
阿新 • • 發佈:2019-02-04
ES6中實現的Promise是 Promise/A+ 規範。
首先,有三種狀態:pending ,fulfilled, rejected。
const PENDING = 'PENDING' const FULFILLED = 'FULFILLED' const REJECTED = 'REJECTED' const isFunction = x => typeof x === 'function' class MyPromise { constructor(handler) { if (!isFunction(handler)) throw new Error('must a parms') this._value = undefined this._status = PENDING this._filfilledQueues = [] this._rejectedQueues = [] try { handler(this._resolve.bind(this), this._reject.bind(this)) } catch (err) { this._reject(err) } } _resolve(val) { if (this._status !== PENDING) return setTimeout(() => { this._status = FULFILLED this._value = val this._filfilledQueues.forEach(item => item(val)) }, 0) } _reject(err) { if (this._status !== PENDING) return this._status = REJECTED this._value = err this._rejectedQueues.forEach(item => item()) } then(onFulfilled, onRejected) { const { _value, _status } = this return new MyPromise((onFulfilledNext, onRejectedNext) => { let fulfilled = value => { try { if (!isFunction(onFulfilled)) { onFulfilledNext(value) } else { let res = onFulfilled(value) if (res instanceof MyPromise) { res.then(onFulfilledNext, onRejectedNext) } else { onFulfilledNext(res) } } } catch (err) { onRejectedNext(err) } } let rejected = error => { try { if (!isFunction(onRejected)) { onRejectedNext(error) } else { let res = onRejected(error) if (res instanceof MyPromise) { res.then(onFulfilledNext, onRejectedNext) } else { onFulfilledNext(res) } } } catch (err) { onRejectedNext(err) } } switch (_status) { case PENDING: this._filfilledQueues.push(fulfilled) this._rejectedQueues.push(rejected) break case FULFILLED: fulfilled(_value) break case REJECTED: rejected(_value) break } }) } catch(onRejected) { return this.then(null, onRejected) } static all(arr) { return new MyPromise((resolve, reject) => { let values = [] let count = 0 for (let [i, p] of arr.entries()) { this.resolve(p).then(res => { values[i] = res count++ if (count === arr.length) { resolve(values) } }, err => { reject(err) }) } }) } static race(arr) { return new MyPromise((resolve, reject) => { for (let p of arr) { this.resolve(p).then(res => { resolve(res) }, err => { reject(err) }) } }) } }