处理异步函数的状态机,拥有链式调用、错误捕获、状态不可逆等特性。为了解决地狱回调而设计的解决方案
const RESOLVED = 'RESOLVED' const REJECTED = 'REJECTED' const PENDING = 'PENDING' const resolvePromise = (promise2, x, resolve, reject) => { if (promise2 === x) { return reject(new TypeError('循环引用报错')) } if (x !== null && (typeof x === 'object' || typeof x === 'function')) { let called; try { let then = x.then if (typeof then === 'function') { then.call(x, y => { if (called) return called = true resolvePromise(promise2, y, resolve, reject) }, e => { if (called) return called = true reject(e) }) } else { resolve(x) } } catch (e) { if (called) return called = true reject(e) } } else { resolve(x) } } class Promise { constructor(executor) { this.status = PENDING this.value = undefined this.reason = undefined this.onfulfilledCallbacks = [] this.onrejectedCallbacks = [] let resolve = (value) => { if (value instanceof Promise) { return value.then(resolve, reject) } if (this.status === PENDING) { this.value = value this.status = RESOLVED this.onfulfilledCallbacks.forEach(fn => fn()) } } let reject = (reason) => { if (this.status === PENDING) { this.reason = reason this.status = REJECTED this.onrejectedCallbacks.forEach(fn => fn()) } } try { executor(resolve, reject) } catch (e) { reject(e) } } then(onfulfilled, onrejected) { onfulfilled = typeof onfulfilled === 'function' ? onfulfilled : v => v; onrejected = typeof onrejected === 'function' ? onrejected : err => { throw err }; let promise2 = new Promise((resolve, reject) => { if (this.status === RESOLVED) { setTimeout(() => { try { let x = onfulfilled(this.value) resolvePromise(promise2, x, resolve, reject) } catch (e) { reject(e) } }) } if (this.status === REJECTED) { setTimeout(() => { try { let x = onrejected(this.reason) resolvePromise(promise2, x, resolve, reject) } catch (e) { reject(e) } }) } if (this.status === PENDING) { this.onfulfilledCallbacks.push(() => { setTimeout(() => { try { let x = onfulfilled(this.value) resolvePromise(promise2, x, resolve, reject) } catch (e) { reject(e) } }) }) this.onrejectedCallbacks.push(() => { setTimeout(() => { try { let x = onrejected(this.reason) resolvePromise(promise2, x, resolve, reject) } catch (e) { reject(e) } }) }) } }) return promise2 } catch (onrejected) { return this.then(null, onrejected) } finally(cb) { return this.then( (data) => { return Promise.resolve(cb()).then(() => data) }, (err) => { return Promise.resolve(cb()).then(() => { throw err }) }) } static resolve(value) { return new Promise((resolve, reject) => { resolve(value) }) } static reject(reason) { return new Promise((resolve, reject) => { reject(reason) }) } static all(promises) { return new Promise((resolve, reject) => { let result = [] let times = 0 const processSuccess = (index, val) => { result[index] = val if (++times === promises.length) { resolve(result) } } for (let i = 0; i < promises.length; i++) { let p = promises[i]; if (p && typeof p.then === 'function') { p.then(data => { processSuccess(i, data) }, reject) } else { processSuccess(i, p) } } }) } static race(promises) { return new Promise((resolve, reject) => { for (let i = 0; i < promises.length; i++) { let p = promises[i]; if (p && typeof p.then === 'function') { p.then(data => { resolve(data) }, reject) } else { resolve(p) } } }) } } Promise.defer = Promise.deferred = function () { let dfd = {} dfd.promise = new Promise((resolve, reject) => { dfd.resolve = resolve; dfd.reject = reject }) return dfd; } module.exports = Promise