promise就是三个状态。利用观察者模式的编程思想,只需要通过特定书写方式注册对应状态的事件处理函数,然后更新状态,调用注册过的处理函数即可。
这个特定方式就是then,done,fail,always…等方法,更新状态就是resolve、reject方法。
/** * Promise类实现原理 * 构造函数传入一个function,有两个参数,resolve:成功回调; reject:失败回调 * state: 状态存储 [PENDING-进行中 RESOLVED-成功 REJECTED-失败] * doneList: 成功处理函数列表 * failList: 失败处理函数列表 * done: 注册成功处理函数 * fail: 注册失败处理函数 * then: 同时注册成功和失败处理函数 * always: 一个处理函数注册到成功和失败 * resolve: 更新state为:RESOLVED,并且执行成功处理队列 * reject: 更新state为:REJECTED,并且执行失败处理队列 **/ class PromiseNew { constructor(fn) { this.state = 'PENDING'; this.doneList = []; this.failList = []; fn(this.resolve.bind(this), this.reject.bind(this)); } // 注册成功处理函数 done(handle) { if (typeof handle === 'function') { this.doneList.push(handle); } else { throw new Error('缺少回调函数'); } return this; } // 注册失败处理函数 fail(handle) { if (typeof handle === 'function') { this.failList.push(handle); } else { throw new Error('缺少回调函数'); } return this; } // 同时注册成功和失败处理函数 then(success, fail) { this.done(success || function () { }).fail(fail || function () { }); return this; } // 一个处理函数注册到成功和失败 always(handle) { this.done(handle || function () { }).fail(handle || function () { }); return this; } // 更新state为:RESOLVED,并且执行成功处理队列 resolve() { this.state = 'RESOLVED'; let args = Array.prototype.slice.call(arguments); setTimeout(function () { this.doneList.forEach((item, key, arr) => { item.apply(null, args); arr.shift(); }); }.bind(this), 200); } // 更新state为:REJECTED,并且执行失败处理队列 reject() { this.state = 'REJECTED'; let args = Array.prototype.slice.call(arguments); setTimeout(function () { this.failList.forEach((item, key, arr) => { item.apply(null, args); arr.shift(); }); }.bind(this), 200); } } // 下面一波骚操作 new PromiseNew((resolve, reject) => { resolve('hello world'); // reject('you are err'); }).then((res) => { console.log(res); }, (error) => { console.log(error); })
解释:当我们调用new Promise(fn)时,就会立即执行第一个参数fn。上面案例中,先将then(done,fail)对应的回调函数分别加入到doneList或者failList中。
当异步代码执行完毕,就调用resolve方法,此时改变promise的状态为resolved,并执行doneList里面的回调函数。如果执行失败,则调用fail方法,此时改变promise的状态为rejected,并执行failList里面的回调函数。