實現符合 Promise/A+ 規範的Promise
實現一個符合 Promise/A+ 規範的 MyPromise,並實現 resolve、reject、all、race等靜態方法。
promise
- 創建Promise 方法
- Promise 接收一個
executor
回掉函數 - Promise 三個狀態
pedding
- 可以變為
fulfilled
成功態 或者rejected
失敗態
fulfilled
- 不可改變的成功態
rejected
- 不可改變失敗態
- onResolvedCallbacks和onRejectedCallbacks
- 分別存儲成功 成功和失敗的回調函數
- resolve
- promise專向成功態調用的函數,接收
value
參數
- reject
- promise轉向失敗態調用的函數,接受
reason
參數
function Promise(executor) { let self = this; self.status = pending; //存放成功回調的數組 self.onResolvedCallbacks =[]; //存放失敗回調的數組 self.onRejectedCallbacks =[]; function resolve(value) { if(self.status == pending){ self.status = fulfilled; self.value = value;//成功後得到一個值,這個值不能改 self.onResolvedCallbacks.forEach(cb=>cb(self.value))// } } function reject(reason) { if(self.status == pending){ self.status = rejected; self.value = reason; self.onRejectedCallbacks.forEach(cb=>cb(self.value)) } } try{ executor(resolve,reject) }catch (e){ //如果函數執行失敗了,reject這個promise reject(e) }}
Promise.prototype.then
鏈式調用返回一個新的Promise,將第一次的返回值,作為下一次成功回掉函數的參數
onFulfilled
和onRejected
- 一個promise.then方法接收兩個參數
onFilfiled
和onRejected
- 如果成功和失敗的回調沒有傳,則表示這個then沒有任何邏輯,只會把值往後拋
onFulfilled
- 成功時調用
- 並把成功的結果傳遞給
onFulfilled
- 不能調用多次
onRejected
- 失敗時調用
- 並把失敗的結果傳遞給
onRejected
- 不能調用多次
- then會調用多次,之後返回一個新的promise
- promise2 = promise1.then(onFulfilled, onRejected)
- 如果
onFulfilled
或onRejected
返回x
解析promise 執行 resolvePromise方法
Promise.prototype.then = function (onFulfilled,onRejected) { onFulfilled = typeof onFulfilled == function?onFulfilled:value=>value; onRejected = typeof onRejected == function?onRejected:reason=>{throw reason}; let self = this; let promise2; //當前promise已經是成功態了,onFulfilled直接取值 if(self.status == fulfilled){ return promise2 = new Promise(function (resolve,reject) { try{ let x = onFulfilled(self.value); resolvePromise(promise2,x,resolve,reject) }catch (e){ reject(e) } }); } if(self.status == rejected){ return promise2 = new Promise(function (resolve,reject) { try{ let x = onRejected(self.value); resolvePromise(promise2,x,resolve,reject) }catch (e){ reject(e) } }) } if(self.status == pending){ return promise2 = new Promise(function(resolve,reject){ self.onResolvedCallbacks.push(function(){ try{ let x =onFulfilled(self.value); //如果獲取到了返回值x,會走解析promise的過程 resolvePromise(promise2,x,resolve,reject); }catch(e){ reject(e); } }); self.onRejectedCallbacks.push(function(){ try{ let x =onRejected(self.value); resolvePromise(promise2,x,resolve,reject); }catch(e){ reject(e); } }); }); }};
The Promise resolvePromise 解析方法
- 如果
x
===當前promise2
不能返回當前Promise,那麼會拋出錯誤new TypeError(循環引用)
x
是一個Promise
- 當前
promise2
等待x
完成,x
有可能也是一個Promise 執行resolvePromise()
- x 如果不是對象(不包括 null)或者函數,執行
resolve(x)
- 獲取 x.then 賦值給 then
- then 如果是 function
- 把 x做為 this 調用then,第一個參數是
resolvePromise2
,第二個參數是rejectPromise2
resolvePromise2
和rejectPromise2
只有第一次調用有效resolvePromise2
參數為 y,執行resolvePromise(promise, y, resolve, reject)
- then 如果不是 function
- 執行
resolve(x)
function resolvePromise(promise2,x,resolve,reject){ if(promise2 === x){ return reject(new TypeError(循環引用)); } let called = false;//promise2是否已經resolve 或reject了 if(x instanceof Promise){ if(x.status == pending){ x.then(function(y){ resolvePromise(promise2,y,resolve,reject); },reject); }else{ x.then(resolve,reject); } //x是一個thenable對象或函數,只要有then方法的對象, }else if(x!= null &&((typeof x==object)||(typeof x == function))){ try{ let then = x.then; if(typeof then == function){ //有些promise會同時執行成功和失敗的回調 then.call(x,function(y){ //如果promise2已經成功或失敗了,則不會再處理了 if(called)return; called = true; resolvePromise(promise2,y,resolve,reject) },function(err){ if(called)return; called = true; reject(err); }); }else{ //到此的話x不是一個thenable對象,那直接把它當成值resolve promise2就可以了 resolve(x); } }catch(e){ if(called)return; called = true; reject(e); } }else{ //如果X是一個普通 的值,則用x的值去resolve promise2 resolve(x); }}
Promise.prototype.catch
- 直傳失敗的回掉
Promise.prototype.catch = function(onRejected){ this.then(null,onRejected);}
Promise.all
- 接收Promise數組,全部完成才會成功,有一個失敗,整個Promise失敗
function gen(times,cb){ let result = [],count=0; return function(i,data){ result[i] = data; if(++count==times){ cb(result); } }}Promise.all = function(promises){ return new Promise(function(resolve,reject){ let done = gen(promises.length,resolve); for(let i=0;i<promises.length;i++){ promises[i].then(function(data){ done(i,data); },reject); } });}
Promise.race
- 接收Promise數組,一個成功就成功了,一個失敗就失敗了
Promise.race = function(promises){ return new Promise(function(resolve,reject){ for(let i=0;i<promises.length;i++){ promises[i].then(resolve,reject); } });}
Promise.resolve
Promise.resolve = function(value){ return new Promise(function(resolve){ resolve(value); });}
Promise.reject
Promise.reject = function(reason){ return new Promise(function(resolve,reject){ reject(reason); });}
源碼
參考資料
- Promise/A+規範
- Promise/A+規範(英文)
- JavaScript Promise迷你書(中文版)
推薦閱讀: