手寫一個MyPromise建構函式
阿新 • • 發佈:2021-12-01
參考網上資料,自己整理了一下思路
首先是一個最簡化的MyPromise建構函式,引數是executor執行器函式。
接下來是,給這個建構函式增加then方法和catch方法。
列印結果是
最後一步是使建構函式可以鏈式呼叫。
function MyPromise(excutor) { console.log('進入MyPromise構造器'); const _PENDING = 'pending'; const _RESOLVED = 'resolved'; const _REJECTED = 'rejected'; const self = this; // 定義一個this指向, 避免在當前作用域下的this混亂self.PromiseStatus = _PENDING; self.PromiseValue = undefined; self.fullFilledList = []; // 用來儲存Promise.then成功的回撥函式 self.rejectedList = []; // 用來儲存Promise.then和Promise.catch失敗的回撥函式 // success const resolve = data => { console.log('使用者呼叫resolve方法,狀態被推向resolved狀態,並且將使用者傳遞進來的資料賦值給PromiseValue');if (self.PromiseStatus === _PENDING) { self.PromiseStatus = _RESOLVED; self.PromiseValue = data; self.fullFilledList.forEach(item => { console.log('一旦使用者狀態被推向resolved狀態則呼叫fullFilledList裡面儲存的成功的回撥函式'); item(); }); } } // error const reject = error => { console.log('使用者呼叫reject方法,狀態被推向rejected狀態,並且將使用者傳遞進來的資料賦值給PromiseValue'); if (self.PromiseStatus === _PENDING) { self.PromiseStatus = _REJECTED; self.PromiseValue = error; self.rejectedList.forEach(item => { console.log('一旦使用者狀態被推向rejected狀態則呼叫rejectedList裡面儲存的失敗的回撥函式'); item(); }); } } try { console.log('到達立即執行器'); excutor(resolve,reject); } catch(error) { reject(error); } MyPromise.prototype.then = (thenable, catchable) => { console.log('進入then函式'); // 如果當前狀態已經為已決階段的兩種狀態了, 那麼回撥函式會被立即呼叫並執行 // 因為catchable很有可能不傳遞, 所以必須容錯 catchable = typeof catchable === 'function' ? catchable : err => { throw err }; if (self.PromiseStatus === _RESOLVED) { // console.log('MyPromise例項是resolved狀態, 呼叫成功回撥函式thenable-then,並返回PromiseValue'); // thenable(self.PromiseValue) console.log('MyPromise例項是resolved狀態,為了鏈式呼叫需要return出一個新的MyPromise例項'); return new MyPromise((resolve, reject) => { try { const x = thenable(self.PromiseValue); // thenable回撥函式return出的內容 if (x instanceof MyPromise) { x.then(resolve, reject) // ??? 以後補充 } else { resolve(x) // 將初始的pending狀態推向resolved狀態 } } catch (err) { reject(err) } }) } if (self.PromiseStatus === _REJECTED) { // console.log('MyPromise例項是rejected狀態, 呼叫失敗回撥函式catchable-then,並返回PromiseValue'); // catchable(self.PromiseValue) console.log('MyPromise例項是rejected狀態,為了鏈式呼叫需要return出一個新的MyPromise例項'); return new MyPromise((resolve, reject) => { try { console.log('呼叫失敗回撥函式catchable-then,並返回PromiseValue'); const x = catchable(self.PromiseValue) if (x instanceof MyPromise) { x.then(resolve, reject) } else { resolve(x) } } catch (err) { reject(err) } }) } if (self.PromiseStatus === _PENDING) { console.log('MyPromise例項是pending狀態'); return new MyPromise((resolve, reject) => { self.fullFilledList.push(() => { const x = thenable(self.PromiseValue) if (x instanceof MyPromise) { x.then(resolve, reject) } else { resolve(x) } }) self.rejectedList.push(() => { try { const x = catchable(self.PromiseValue) if (x instanceof Promise) { x.then(resolve, reject) } else { resolve(x) } } catch (err) { reject(err) } }) }) } } MyPromise.prototype.catch = catchable => { console.log('進入catch函式'); // if (self.PromiseStatus === _REJECTED) { // console.log('MyPromise例項是rejected狀態, 呼叫失敗回撥函式catchable-catch'); // catchable(self.PromiseValue) // } return self.then(null, catchable); } }; const myPromise = new MyPromise((resolve, reject) => { // 立即執行且順序執行 console.log('我會立即執行'); reject('hello'); }) const myPromise1 = myPromise.then(res => { console.log(res, 'thenable執行-then'); }, err => { console.log(err, 'catchable執行-then'); return err; }) myPromise1.then(res => { console.log(res, '第二個then'); return res + ' world'; }).then(res => { console.log(res, '第三個then'); }) // const myPromise2 = myPromise.catch(err => { // console.log(err, 'catchable執行-catch'); // })
後續再完善。