本文侧重侧重讲解Promise的原理,如果对Promise使用不太熟的小伙伴可参考阮一峰老师的文章ECMAScript 6 入门。
Promise有三种状态,分别是pending、fulfilled和reject,一旦改变便不会再更改。
所以第一步,我们把这个功能先实现。
export default class MyPromise { constructor(handle) { this['[[PromiseState]]'] = "pending" //Promise的状态 this['[[PromiseResult]]'] = undefined; //Promise的值 handle(this._resolve,this._reject) } _resolve = (val) => { //1.修改Promise的状态 2.修改Promise的值 if (this['[[PromiseState]]'] === "pending") { this['[[PromiseState]]'] = "fulfilled" this['[[PromiseResult]]'] = val; } } _reject = (err) => { if (this['[[PromiseState]]'] === "pending") { this['[[PromiseState]]'] = "rejected"; this['[[PromiseResult]]'] = err; } } }
第二步 实现then方法,then方法可以接受两个回调函数作为参数。这个两个回调函数接受Promise的值作为参数。
export default class MyPromise { constructor(handle) { this['[[PromiseState]]'] = "pending" //promise的状态 this['[[PromiseResult]]'] = undefined; //promise的值 this.resolveFn = undefined; this.rejectFn = undefined; handle(this._resolve,this._reject) } _resolve = (val) => { //1.修改promise的状态 2.修改promise的值 if (this['[[PromiseState]]'] === "pending") { this['[[PromiseState]]'] = "fulfilled" this['[[PromiseResult]]'] = val; setTimeout(()=>{ this.resolveFn(val) }) } } _reject = (err) => { if (this['[[PromiseState]]'] === "pending") { this['[[PromiseState]]'] = "rejected"; this['[[PromiseResult]]'] = err; setTimeout(()=>{ this.rejectFn(err) }) } } then(onResolved,onRejected){ this.resolveFn = onResolved; this.rejectFn = onRejected; } }
写到此处then有4个问题还没解决 。
1.多个then的问题(不是链式调用)
即如下面这样多次调用then。
const p1 = new Promise((res)=>{ setTimeout(()=>{ res(1) }) }) p1.then((value)=>{ console.log(value + 1) // 2 }) p1.then((value)=>{ console.log(value + 2) // 3 })
2、then的同步执行顺序问题(微任务、宏任务)。
3、then的链式调用。
第三步解决多个then的调用问题。将then接受的回调函数用数组收集起来,解决多个then的调用问题。
export default class MyPromise { constructor(handle) { this['[[PromiseState]]'] = "pending" //promise的状态 this['[[PromiseResult]]'] = undefined; //promise的值 this.onResolvedCallback = [] // Promise resolve时的回调函数集 this.onRejectedCallback = [] // Promise reject时的回调函数集 // this.resolveFn = undefined; // this.rejectFn = undefined; handle(this._resolve,this._reject) } _resolve = (val) => { //1.修改promise的状态 2.修改promise的值 if (this['[[PromiseState]]'] === "pending") { this['[[PromiseState]]'] = "fulfilled" this['[[PromiseResult]]'] = val; setTimeout(()=>{ let cb; while(cb = this.onResolvedCallback.shift()) { typeof cb ==='function' && cb(val); } }) } } _reject = (err) => { if (this['[[PromiseState]]'] === "pending") { this['[[PromiseState]]'] = "rejected"; this['[[PromiseResult]]'] = err; setTimeout(()=>{ let cb; while(cb = this.onRejectedCallback.shift()) { typeof cb ==='function' && cb(err); } }) } } then(onResolved,onRejected){ this.onResolvedCallback.push(onResolved); this.onRejectedCallback.push(onRejected); } }
第四步、then的同步执行顺序问题。then里面的回调函数属于微任务,当前所有同步代码执行完毕然后执行then里面的回调函数,再执行定时器这些宏任务。
const my = new MyPromise((res)=>{ console.log('Promise') setTimeout(()=>{ console.log(1) }) res(2); }); my.then((value)=>{ console.log(value) }); /*打印的顺序为promise、1、2,这个顺序是不对的。 上述代码中,正确的执行顺序应该是,MyPromise新建后立即执行,首先输出Promise,然后输出2,最后输出1。
为了让then收集的回调函数执行的时候有微任务的效果,可以用MutationObserver模拟一下,MutationObserver的具体用法可以参照MDN。
export default class MyPromise { constructor(handle) { this['[[PromiseState]]'] = "pending" //promise的状态 this['[[PromiseResult]]'] = undefined; //promise的值 this.onResolvedCallback = [] // Promise resolve时的回调函数集 this.onRejectedCallback = [] // Promise reject时的回调函数集 // this.resolveFn = undefined; // this.rejectFn = undefined; handle(this._resolve,this._reject) } _resolve = (val) => { //1.修改promise的状态 2.修改promise的值 if (this['[[PromiseState]]'] === "pending") { this['[[PromiseState]]'] = "fulfilled" this['[[PromiseResult]]'] = val; const executor = () => { let cb; while(cb = this.onResolvedCallback.shift()) { typeof cb ==='function' && cb(val); } } const obj = new MutationObserver(executor); obj.observe(document.body,{ attributes:true }); document.body.setAttribute("Promise","MyPromise") // setTimeout(()=>{ // let cb; // while(cb = this.onResolvedCallback.shift()) { // typeof cb ==='function' && cb(val); // } // }) } } _reject = (err) => { if (this['[[PromiseState]]'] === "pending") { this['[[PromiseState]]'] = "rejected"; this['[[PromiseResult]]'] = err; // setTimeout(()=>{ // let cb; // while(cb = this.onRejectedCallback.shift()) { // typeof cb ==='function' && cb(err); // } // }) const executor = () => { let cb; while(cb = this.onRejectedCallback.shift()) { typeof cb ==='function' && cb(val); } } const obj = new MutationObserver(executor); obj.observe(document.body,{ attributes:true }); document.body.setAttribute("Promise","MyPromise") } } then(onResolved,onRejected){ this.onResolvedCallback.push(onResolved); this.onRejectedCallback.push(onRejected); } }
第五步、解决then的链式调用的问题。then调用后会返回一个新的Promise实例。
export default class MyPromise { constructor(handle) { this['[[PromiseState]]'] = "pending" //promise的状态 this['[[PromiseResult]]'] = undefined; //promise的值 this.onResolvedCallback = [] // Promise resolve时的回调函数集 this.onRejectedCallback = [] // Promise reject时的回调函数集 // this.resolveFn = undefined; // this.rejectFn = undefined; handle(this._resolve, this._reject) } _resolve = (val) => { //1.修改promise的状态 2.修改promise的值 if (this['[[PromiseState]]'] === "pending") { this['[[PromiseState]]'] = "fulfilled"; this['[[PromiseResult]]'] = val; const executor = () => { let cb; while (cb = this.onResolvedCallback.shift()) { cb && cb(val); } } const obj = new MutationObserver(executor); obj.observe(document.body, { attributes: true }); document.body.setAttribute("Promise", "MyPromise") // setTimeout(()=>{ // let cb; // while(cb = this.onResolvedCallback.shift()) { // typeof cb ==='function' && cb(val); // } // }) } } _reject = (err) => { if (this['[[PromiseState]]'] === "pending") { this['[[PromiseState]]'] = "rejected"; this['[[PromiseResult]]'] = err; // setTimeout(()=>{ // let cb; // while(cb = this.onRejectedCallback.shift()) { // typeof cb ==='function' && cb(err); // } // }) const executor = () => { let cb; while (cb = this.onRejectedCallback.shift()) { cb && cb(val); } } const obj = new MutationObserver(executor); obj.observe(document.body, { attributes: true }); document.body.setAttribute("Promise", "MyPromise") } } then(onResolved, onRejected) { return new MyPromise((resolve,reject) => { const resloveFn = (val) => { const res = typeof onResolved === 'function' && onResolved(val); //如果then里面的回调函数返回的是一个Promise实例 if (res instanceof MyPromise) { res.then((result) => { resolve(result) }) } else { console.log(res,'执行的结果') resolve(res) } } this.onResolvedCallback.push(resloveFn); const rejectFn = (err) => { typeof onRejected === 'function' && onRejected(err); reject(err); } this.onRejectedCallback.push(rejectFn); }) } }
第六步、Promise的一些其他静态方法
export default class MyPromise { constructor(handle) { this['[[PromiseState]]'] = "pending";//promise的状态 this['[[PromiseResult]]'] = undefined; //promise的值 this.onResolvedCallback = [];// Promise resolve时的回调函数集 this.onRejectedCallback = [];// Promise reject时的回调函数集 // this.resolveFn = undefined; // this.rejectFn = undefined; handle(this._resolve, this._reject); } _resolve = (val) => { //1.修改promise的状态 2.修改promise的值 if (this['[[PromiseState]]'] === "pending") { this['[[PromiseState]]'] = "fulfilled"; this['[[PromiseResult]]'] = val; const executor = () => { let cb; while (cb = this.onResolvedCallback.shift()) { cb && cb(val); } } const obj = new MutationObserver(executor); obj.observe(document.body, { attributes: true }); document.body.setAttribute("Promise", "MyPromise"); // setTimeout(()=>{ // let cb; // while(cb = this.onResolvedCallback.shift()) { // typeof cb ==='function' && cb(val); // } // }) } } _reject = (err) => { if (this['[[PromiseState]]'] === "pending") { this['[[PromiseState]]'] = "rejected"; this['[[PromiseResult]]'] = err; // setTimeout(()=>{ // let cb; // while(cb = this.onRejectedCallback.shift()) { // typeof cb ==='function' && cb(err); // } // }) const executor = () => { let cb; while (cb = this.onRejectedCallback.shift()) { cb && cb(err); } } const obj = new MutationObserver(executor); obj.observe(document.body, { attributes: true }); document.body.setAttribute("Promise", "MyPromise"); } } then(onResolved, onRejected) { return new MyPromise((resolve, reject) => { const resloveFn = (val) => { const res = typeof onResolved === 'function' && onResolved(val); //如果then里面的回调函数返回的是一个Promise实例 if (res instanceof MyPromise) { res.then((result) => { resolve(result); }) } else { resolve(res); } } this.onResolvedCallback.push(resloveFn); const rejectFn = (err) => { typeof onRejected === 'function' && onRejected(err); reject(err); } this.onRejectedCallback.push(rejectFn); }) } static resolve(value) { return new MyPromise(resolve => { resolve(value); }) } static reject(err) { return new MyPromise((resolve, reject) => { reject(err); }) } static race(arr) { return new MyPromise((resolve, reject) => { arr.forEach((promise) => { promise.then((value) => { resolve(value); }, (error) => { reject(error); }) }) }) } static all(promises) { return new MyPromise((resolve) => { const result = []; let index = 0; let len = promises.length; if (len === 0) { resolve(result); return; } for (let i = 0; i < len; i++) { promises[i].then((res) => { result[i] = res; index++; if (index === len) { resolve(result); } }) } }) } static allSettled(promises) { return new MyPromise((resolve, reject) => { const result = []; let index = 0; let len = promises.length; if (len === 0) { resolve(result); } for(let i = 0; i < len; i++){ const obj = {}; promises[i].then((val)=>{ obj.status = "fulfilled"; obj.value = val; result[i] = obj; index++; if (index === len) { resolve(result); } },(err)=>{ obj.status = "rejected"; obj.reason = err; result[i] = obj; index++; if (index === len) { resolve(result); } }) } }) } }
本文虽然有一些细节的地方没考虑周全,达不到Promise/A+的标准,但基本雏形都在适合第一次手写Promise的小伙伴入个门。