BFE.devAI解答 - JavaScript 代码题
67. 请自行实现Promise
以下是一个可能的解答:
class MyPromise { constructor(executor) { this.state = 'pending'; this.value = undefined; this.reason = undefined; this.onResolvedCallbacks = []; this.onRejectedCallbacks = []; const resolve = value => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; this.onResolvedCallbacks.forEach(cb => cb(this.value)); } }; const reject = reason => { if (this.state === 'pending') { this.state = 'rejected'; this.reason = reason; this.onRejectedCallbacks.forEach(cb => cb(this.reason)); } }; try { executor(resolve, reject); } catch (error) { reject(error); } } then(onFulfilled, onRejected) { const promise2 = new MyPromise((resolve, reject) => { if (this.state === 'fulfilled') { setTimeout(() => { try { const x = onFulfilled(this.value); this.resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }) } else if (this.state === 'rejected') { setTimeout(() => { try { const x = onRejected(this.reason); this.resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }) } else if (this.state === 'pending') { this.onResolvedCallbacks.push(() => { setTimeout(() => { try { const x = onFulfilled(this.value); this.resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }) }) this.onRejectedCallbacks.push(() => { setTimeout(() => { try { const x = onRejected(this.reason); this.resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }) }) } }) return promise2; } catch(onRejected) { return this.then(null, onRejected); } resolvePromise(promise2, x, resolve, reject) { if (x === promise2) { return reject(new TypeError('Chaining cycle detected')); } let called = false; if (x instanceof MyPromise) { x.then( value => { if (called) return; called = true; this.resolvePromise(promise2, value, resolve, reject); }, reason => { if (called) return; called = true; reject(reason) } ) } else if (x !== null && (typeof x === 'object' || typeof x === 'function')) { try { const then = x.then; if (typeof then === 'function') { then.call(x, value => { if (called) return; called = true; this.resolvePromise(promise2, value, resolve, reject); }, reason => { if (called) return; called = true; reject(reason); } ) } else { resolve(x); } } catch (error) { if (called) return; called = true; reject(error); } } else { resolve(x); } } static resolve(value) { if (value instanceof MyPromise) { return value; } return new MyPromise(resolve => resolve(value)); } static reject(reason) { return new MyPromise((_, reject) => reject(reason)); }}
这个实现使用类构造函数创建promise,并存储状态、值和回调函数列表。它实现了两个核心器方法 then() 和 catch() 以支持链式调用。
函数 resolvePromise() 处理可能的快速解决(fulfillment)结果,并将其解析为与当前promises级联的结果。
最后,静态方法 resolve() 、reject() 从构造函数中创建新的promises对外提供了帮助函数。