第一步:promise的聲明git
class Promise{ // 構造器 constructor(executor){ // 成功 let resolve = () => { }; // 失敗 let reject = () => { }; // 當即執行 executor(resolve, reject); } }
第二步:三個基本狀態(pending、fulfilled、rejected)github
class Promise{ constructor(executor){ // 初始化state爲等待態 this.state = 'pending'; // 成功的值 this.value = undefined; // 失敗的緣由 this.reason = undefined; let resolve = value => { // state改變,resolve調用就會失敗 if (this.state === 'pending') { // resolve調用後,state轉化爲成功態 this.state = 'fulfilled'; // 儲存成功的值 this.value = value; } }; let reject = reason => { // state改變,reject調用就會失敗 if (this.state === 'pending') { // reject調用後,state轉化爲失敗態 this.state = 'rejected'; // 儲存失敗的緣由 this.reason = reason; } }; // 若是executor執行報錯,直接執行reject try{ executor(resolve, reject); } catch (err) { reject(err); } } }
第三步:then方法(兩個參數:onFulfilled,onRejected)數組
onFulfilled,onRejected若是他們是函數,promise
則必須分別在fulfilled,rejected後被調用,value或reason依次做爲他們的第一個參數異步
class Promise{ constructor(executor){...} // then 方法 有兩個參數onFulfilled onRejected then(onFulfilled,onRejected) { // 狀態爲fulfilled,執行onFulfilled,傳入成功的值 if (this.state === 'fulfilled') { onFulfilled(this.value); }; // 狀態爲rejected,執行onRejected,傳入失敗的緣由 if (this.state === 'rejected') { onRejected(this.reason); }; } }
第四步:異步的實現函數
當resolve在setTomeout內執行,then時state仍是pending等待狀態this
咱們就須要在then調用的時候,將成功和失敗存到各自的數組,一旦reject或者resolve,就調用它們spa
class Promise{ constructor(executor){ this.state = 'pending'; this.value = undefined; this.reason = undefined; // 成功存放的數組 this.onResolvedCallbacks = []; // 失敗存放法數組 this.onRejectedCallbacks = []; let resolve = value => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; // 一旦resolve執行,調用成功數組的函數 this.onResolvedCallbacks.forEach(fn=>fn()); } }; let reject = reason => { if (this.state === 'pending') { this.state = 'rejected'; this.reason = reason; // 一旦reject執行,調用失敗數組的函數 this.onRejectedCallbacks.forEach(fn=>fn()); } }; try{ executor(resolve, reject); } catch (err) { reject(err); } } then(onFulfilled,onRejected) { if (this.state === 'fulfilled') { onFulfilled(this.value); }; if (this.state === 'rejected') { onRejected(this.reason); }; // 當狀態state爲pending時 if (this.state === 'pending') { // onFulfilled傳入到成功數組 this.onResolvedCallbacks.push(()=>{ onFulfilled(this.value); }) // onRejected傳入到失敗數組 this.onRejectedCallbacks.push(()=>{ onRejected(this.reason); }) } } }
第五步:鏈式調用code
new Promise().then().then()
這就是鏈式調用,用來解決回調地獄對象
一、爲了達成鏈式,咱們默認在第一個then裏返回一個promise,叫promise2,將它傳遞下一個then中。
二、咱們須要在then中return一個參數,這個就叫x,x若是是promise,則取它的結果,做爲promise2成功的結果。若是是普通值,直接做爲promise2成功的結果,判斷x的函數叫resolvePromise,帶四個參數(promise2,x,resolve,reject)
class Promise{ constructor(executor){ this.state = 'pending'; this.value = undefined; this.reason = undefined; this.onResolvedCallbacks = []; this.onRejectedCallbacks = []; let resolve = value => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; this.onResolvedCallbacks.forEach(fn=>fn()); } }; let reject = reason => { if (this.state === 'pending') { this.state = 'rejected'; this.reason = reason; this.onRejectedCallbacks.forEach(fn=>fn()); } }; try{ executor(resolve, reject); } catch (err) { reject(err); } } then(onFulfilled,onRejected) { // 聲明返回的promise2 let promise2 = new Promise((resolve, reject)=>{ if (this.state === 'fulfilled') { let x = onFulfilled(this.value); // resolvePromise函數,處理本身return的promise和默認的promise2的關係 resolvePromise(promise2, x, resolve, reject); }; if (this.state === 'rejected') { let x = onRejected(this.reason); resolvePromise(promise2, x, resolve, reject); }; if (this.state === 'pending') { this.onResolvedCallbacks.push(()=>{ let x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); }) this.onRejectedCallbacks.push(()=>{ let x = onRejected(this.reason); resolvePromise(promise2, x, resolve, reject); }) } }); // 返回promise,完成鏈式 return promise2; } }
第六步:實現resolvePromise函數
function resolvePromise(promise2, x, resolve, reject){ // 循環引用報錯 if(x === promise2){ // reject報錯(檢測到promise的連接循環)
return reject(new TypeError('Chaining cycle detected for promise')); } // 防止屢次調用 let called; // x不是null 且x是對象或者函數 if (x != null && (typeof x === 'object' || typeof x === 'function')) { try { // A+規定,聲明then = x的then方法 let then = x.then; // 若是then是函數,就默認是promise了 if (typeof then === 'function') { // 就讓then執行 第一個參數是this 後面是成功的回調 和 失敗的回調 then.call(x, y => { // 成功和失敗只能調用一個 if (called) return; called = true; // resolve的結果依舊是promise 那就繼續解析 resolvePromise(promise2, y, resolve, reject); }, err => { // 成功和失敗只能調用一個 if (called) return; called = true; reject(err);// 失敗了就失敗了 }) } else { resolve(x); // 直接成功便可 } } catch (e) { // 也屬於失敗 if (called) return; called = true; // 取then出錯了那就不要在繼續執行了 reject(e); } } else { resolve(x); } }
第七步:解決一些問題
一、onFulfilled或onRejected不能同步被調用,必須異步調用。咱們就用setTimeout解決異步問題
二、onFulfilled返回一個普通的值,成功時直接等於 value => value
三、onRejected返回一個普通的值,失敗時若是直接等於 value => value,則會跑到下一個then中的onFulfilled中,因此直接扔出一個錯誤 reason => throw err
class Promise{ constructor(executor){ this.state = 'pending'; this.value = undefined; this.reason = undefined; this.onResolvedCallbacks = []; this.onRejectedCallbacks = []; let resolve = value => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; this.onResolvedCallbacks.forEach(fn=>fn()); } }; let reject = reason => { if (this.state === 'pending') { this.state = 'rejected'; this.reason = reason; this.onRejectedCallbacks.forEach(fn=>fn()); } }; try{ executor(resolve, reject); } catch (err) { reject(err); } } then(onFulfilled,onRejected) { // onFulfilled若是不是函數,就忽略onFulfilled,直接返回value onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value; // onRejected若是不是函數,就忽略onRejected,直接扔出錯誤 onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err }; let promise2 = new Promise((resolve, reject) => { if (this.state === 'fulfilled') { // 異步 setTimeout(() => { try { let x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }, 0); }; if (this.state === 'rejected') { // 異步 setTimeout(() => { // 若是報錯 try { let x = onRejected(this.reason); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }, 0); }; if (this.state === 'pending') { this.onResolvedCallbacks.push(() => { // 異步 setTimeout(() => { try { let x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }, 0); }); this.onRejectedCallbacks.push(() => { // 異步 setTimeout(() => { try { let x = onRejected(this.reason); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }, 0) }); }; }); // 返回promise,完成鏈式 return promise2; } }
祝賀:一個promise就在本身筆下誕生啦~~
參考資料: