如今Promise用的比較頻繁了,若是哪天忽然不用了,可能邏輯就很差釐清了,回調沒的說是一大把
廢話很少說,進入正題函數
Promise
這個東西很神奇,用起來舒服,若本身寫一下,恐怕還真不簡單,關鍵就一個字「繞」,繞過了也就行了測試
class MyPromise { constructor(excutor) {} then(onfulfilled, onrejected) {} catch(onrejected) {} }
以上也就是大致的結構了this
Promise
的示例var p = new Promise((resolve, reject) => { resolve(1) }) p.then(console.log) p.then(console.log)
以上的輸出結果爲設計
1 1
因此說內部應該有必要存這個結果值,同時還有必要存一系列的回調函數,因此先來看看構造函數的實現code
constructor(excutor) { // 狀態 this._state = 'pending' // 成功回調 this._callbacks_resolved = [] // 失敗回調 this._callbacks_rejected = [] // 執行 excutor((data) => { // 避免重複執行 if (this._state !== 'pending') { return } // 保存結果 this._data = data // 狀態變動 this._state = "resolved" // 處理 this._handle() }, (err) => { if (this._state !== 'pending') { return } // 錯誤信息 this._err = err // 狀態變動 this._state = "rejected" this._handle() }) }
也就是根據對應的狀態執行對應的回調,固然不要忘了處理完以後要清空回調函數
_handle() { if (this._state === 'pending') { return; } // 爲何要延時,then的東西是不能立刻執行的,能夠看看micro-task和macro-task,這裏只能模擬 setTimeout(() => { if (this._state === 'resolved') { this._callbacks_resolved.forEach(cb => cb(this._data)) } else { this._callbacks_rejected.forEach(cb => cb(this._err)) } this._callbacks_resolved = [] this._callbacks_rejected = [] }) }
then
到了關鍵的一步,也就是核心的then
這個then
的放回結果自己就是一個Promise
,因此是能夠無限的套的,也就像這樣.then().then()
還支持值傳遞,上一個沒有處理的,直接流到下一級,上一級把錯誤處理後,下一級狀態變動爲resolved
io
最開始想直接返回this
,發覺這樣問題大了去了,因此得另外new
一個MyPromise
實例,代碼以下console
then(onfulfilled, onrejected) { return new MyPromise((resolve, reject) => { this._callbacks_resolved.push(data => { // 沒有處理,直接日後傳 if (!onfulfilled) { return resolve(data) } try { let r = onfulfilled(data) // 有then函數,就認爲是Promise if (r && typeof r.then === "function") { return r.then(resolve, reject) } resolve(r) } catch(e) { // 有錯誤直接向後傳 reject(e) } }) this._callbacks_rejected.push(err => { if (!onrejected) { return reject(err) } try { let r = onrejected(err) if (r && typeof r.then === "function") { return r.then(resolve, reject) } resolve(r) } catch(e) { reject(e) } }) this._handle() }) }
以上基本功能已經實現完成,最後還有一個catch
函數,很簡單,包裝一下就行了function
catch(onrejected) { return this.then(undefined, onrejected) }
隨便寫了個測試用例class
var p = new MyPromise((resolve, reject) => { resolve(1); }) .then((n) => { console.log(n); return new MyPromise((resolve, reject) => { resolve(2); }); }) .then(console.log) .then(() => { throw new Error("error"); }); p.catch((e) => { console.error(e); }); p.catch((e) => { console.error(e); });
輸出
1 2 error error
徹底符合預期
好了,完結
附上所有代碼
class MyPromise { constructor(excutor) { // 狀態 this._state = "pending"; // 成功回調 this._callbacks_resolved = []; // 失敗回調 this._callbacks_rejected = []; // 執行 excutor( (data) => { // 避免重複執行 if (this._state !== "pending") { return; } // 保存結果 this._data = data; // 狀態變動 this._state = "resolved"; // 處理 this._handle(); }, (err) => { if (this._state !== "pending") { return; } // 錯誤信息 this._err = err; // 狀態變動 this._state = "rejected"; this._handle(); } ); } then(onfulfilled, onrejected) { return new MyPromise((resolve, reject) => { this._callbacks_resolved.push((data) => { // 沒有處理,直接日後傳 if (!onfulfilled) { return resolve(data); } try { let r = onfulfilled(data); // 有then函數 if (r && typeof r.then === "function") { return r.then(resolve, reject); } resolve(r); } catch (e) { // 有錯誤直接向後傳 reject(e); } }); this._callbacks_rejected.push((err) => { if (!onrejected) { return reject(err); } try { let r = onrejected(err); if (r && typeof r.then === "function") { return r.then(resolve, reject); } resolve(r); } catch (e) { reject(e); } }); this._handle() }); } catch(onrejected) { return this.then(undefined, onrejected); } _handle() { if (this._state === "pending") { return; } // 爲何要延時,then的東西是不能立刻執行的,能夠看看micro-task和macro-task,這裏只能模擬 setTimeout(() => { if (this._state === "resolved") { this._callbacks_resolved.forEach((cb) => cb(this._data)); } else { this._callbacks_rejected.forEach((cb) => cb(this._err)); } this._callbacks_resolved = []; this._callbacks_rejected = []; }); } }