class promise { constructor(fn) { this.data = null; this.err = null; this.isPromise = false; this.errFn = null; this.queue = []; this.run = this.run.bind(this); this.error = this.error.bind(this); this.then = this.then.bind(this); this.catch = this.catch.bind(this); this.reslove = this.reslove.bind(this); this.reject = this.reject.bind(this); this.setData = this.setData.bind(this); this.getData = this.getData.bind(this); this.setQueue = this.setQueue.bind(this); this.setErrFn = this.setErrFn.bind(this); this.getErrFn = this.getErrFn.bind(this); this.setPromise = this.setPromise.bind(this); this.getPromise = this.getPromise.bind(this); fn(this.reslove, this.reject); return this; } setPromise() { this.isPromise = !this.isPromise; } getPromise() { return this.isPromise; } setErrFn(fn) { this.errFn = fn; } getErrFn() { return this.errFn; } setQueue(fn) { this.queue.push(fn); } getQueue() { return this.queue; } setData(data) { this.data = data; } getData() { return this.data; } setErr(err) { this.err = err; } getErr() { return this.err; } reslove(data) { if (this.getPromise()) return; this.setPromise(); this.setData(data); this.run(); } reject(err) { if (this.getPromise()) return; this.setPromise(); this.setErr(err); this.error(); } then(fn) { this.setQueue(fn); return this; } catch(fn) { this.setErrFn(fn); } run() { const queue = this.getQueue(); let ret = this.getData(); for(let i = 0; i < queue.length; i++) { // 下面三种方式都可以实现想要的效果 process.nextTick(() => { ret = queue[i](ret); }); // setImmediate(() => { // ret = queue[i](ret); // }); // setTimeout(() => { // ret = queue[i](ret); // }, 0); } } error() { // 下面三种方式都可以实现想要的效果 process.nextTick(() => { this.setErrFn(fn) }); // setImmediate(() => { // this.setErrFn(fn) // }); // setTimeout(() => { // this.getErrFn()(this.getErr()); // }, 0); } } const p = new promise((res, rej) => { setTimeout(() => { console.log('s1'); setTimeout(() => { console.log('s2'); setTimeout(() => { console.log('s3'); res('res'); rej('rej'); console.log('s4'); }, 1000); }, 1000); }, 1000); }); let pp = p .then((data) => { console.log(data); return 't2'; }) .then((data) => { console.log(data); return 't3'; }); pp.then((data) => { console.log(data); }).catch((err) => { console.log(err); });
// 输出
// s1
// s2
// s3
// s4
// res
// t2
// t3
上面代码只是简单的进行基础模拟,让回调可以串行化,没有做错误处理、 API 扩展、参数格式化等操作。
Promise 通过高层次的回调抽离,将代码编写方式从回调改写成了串行,需要在熟练使用的基础上对其内核进行深入的理解才能更加灵活地运用。