简单版:
function MyPromise(exec) { const that = this; that.state = 'PENDING'; that.value = null; that.resolvedCallbacks = []; that.rejectedCallbacks = []; function resolve(v) { if(that.state === 'PENDING') { that.state = 'RESOLVED'; that.value = v; that.resolvedCallbacks.map(cb => cb(that.v)); } } function reject(r) { if(that.state === 'PENDING') { that.state = 'REJECTED'; that.value = r; that.rejectedCallbacks.map(cb => cb(that.v)); } } try { exec(resolve, reject) } catch (e) { reject(e); } } MyPromise.prototype.then = function(onfulfilled, onrejected) { const that = this; onfulfilled = typeof onfulfilled === 'function' ? onfulfilled : v => v; onrejected = typeof onrejected === 'function' ? onrejected : r => {throw r}; if(that.state === 'PENDING') { that.resolvedCallbacks.push(onfulfilled); that.rejectedCallbacks.push(onrejected); } if(that.state === 'RESOLVED') { onfulfilled(that.value); } if(that.state === 'REJECTED') { onrejected(that.value); } }
完整版:
class MyPromise { constructor (execute) { if(typeof execute !== 'function') throw new Error('type error'); const that = this; that.status = 'PENDING'; that.value = null; that.resolvedCallbacks = []; that.rejectedCallbacks = []; try{ execute(that._resolve.bind(that), that._reject.bind(that)); } catch (e) { that._reject(e); } } _resolve (val) { const that = this; const run = () => { if (that.status !== 'PENDING') return; const runFulfilled = (value) => { let cb; while (cb = that.resolvedCallbacks.shift()) { cb(value); } } const runRejected = (error) => { let cb; while (cb = that.rejectedCallbacks.shift()) { cb(error); } } if (val instanceof MyPromise) { val.then(value => { that.value = value; that.status = 'RESOLVED'; runFulfilled(value); }, err => { that.value = err; that.status = 'REJECTED'; runRejected(err); }) } else { that.value = val; that.status = 'RESOLVED'; runFulfilled(val); } } setTimeout(run, 0) } _reject (err) { const that = this; if (that.status !== 'PENDING') return; const run = () => { that.status = 'REJECTED'; that.value = err; let cb; while (cb = that.rejectedCallbacks.shift()) { cb(err); } } setTimeout(run, 0) } then (onFulfilled, onRejected) { const that = this; return new MyPromise((onFulfilledNext, onRejectedNext) => { let fulfilled = value => { try { if (typeof onFulfilled !== 'function') { 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 (typeof onRejected !== 'function') { onRejectedNext(error); } else { let res = onRejected(error); if (res instanceof MyPromise) { res.then(onFulfilledNext, onRejectedNext); } else { onFulfilledNext(res); } } } catch (err) { onRejectedNext(err); } } switch(that.status) { case 'PENDING':{ that.resolvedCallbacks.push(onFulfilled); that.rejectedCallbacks.push(onRejected); };break; case 'RESOLVED':onFulfilled(that.value);break; case 'REJECTED':onRejected(that.value);break; } }) } _catch (onRejected) { return this.then(undefined, onRejected) } static resolve (value) { if (value instanceof MyPromise) return value return new MyPromise(resolve => resolve(value)) } static reject (value) { return new MyPromise((resolve ,reject) => reject(value)) } static all (list) { return new MyPromise((resolve, reject) => { let values = [] let count = 0 for (let [i, p] of list.entries()) { this.resolve(p).then(res => { values[i] = res count++ if (count === list.length) resolve(values) }, err => { reject(err) }) } }) } static race (list) { return new MyPromise((resolve, reject) => { for (let p of list) { this.resolve(p).then(res => { resolve(res) }, err => { reject(err) }) } }) } finally (cb) { return this.then( value => MyPromise.resolve(cb()).then(() => value), reason => MyPromise.resolve(cb()).then(() => { throw reason }) ); } }