最近在掘金上刷面試題的時候不可或非的屢次遇到了Promise的問題,因而經過萬能的搜索引擎,研究一番以後終於對Promise的源碼纔有了一個初步的理解,但願小夥伴能在此獲得一點收穫javascript
new 一個promise的時候須要傳遞一個執行器函數,當即執行
執行器函數只接受兩個參數 resolve reject
Promise有三個狀態 pedding fulfilled rejectedjava
狀態改變只能由pendding -> fulfilled 或者 pendding -> rejected
狀態一經肯定就沒法改變面試
Promise 的 then 能夠鏈式調用(返回一個promise對象)
可接收兩個參數(可缺省),一個是成功的回調onFulfilled 一個是失敗的回調onRejected數組
若是成功且有返回值,則若是返回值爲Promise對象則等待promise執行完成
若是成功則走下一個Promise成功的回調不然就走失敗的回調promise
若是返回值是其餘類型則直接做爲下一個then對應的成功或失敗的回調(在成功的回調返回就走下一個then成功的回調,反之亦然)異步
const PENDDING='pendding';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected'
function Promise(fn){
let self = this;
/**初始化狀態*/
self.status=PENDDING;
/**保存成功回調函數*/
self.onFulfilledCallBack=[];
/**保存失敗的回到數組*/
self.onRejectedCallBack=[];
/**執行成功回調 */
function resolve(value){
if(self.status===PENDDING){
self.status=FULFILLED;
self.value=value;
self.onFulfilledCallBack.forEach(fn=>fn(self.value))
}
}
/**失敗回調*/
function reject(reason){
if(self.status===PENDDING){
self.status=REJECTED;
self.reason=reason;
self.onRejectedCallBack.forEach(fn=>fn(self.reason))
}
}
/**當即執行傳入的函數,並加一層捕獲異常 */
try {
fn(resolve,reject)
} catch (error) {
reject(error)
}
}
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=new Promise(function(resolve,reject){
if(self.status===FULFILLED){
try {
/**由於Promise是屬於微任務,因此在這裏須要在外層包裹一個setTimeout 保證它處於異步隊列(關於這個問題的具體緣由能夠百度一下js事件循環機制) */
setTimeout(()=>{
let x = onFulfilled(self.value);
resolvePromise(promise2,x,resolve,reject)
})
} catch (error) {
reject(error)
}
}else if(self.status===REJECTED){
try {
setTimeout(()=>{
let x = onRejected(self.reason);
resolvePromise(promise2,x,resolve,reject)
})
} catch (error) {
reject(error)
}
}else if(self.status===PENDDING){
/** 若是在調用then函數的時候promise狀態還處於pendding狀態 則將處理函數分別存入對應的成功或失敗的處理函數數組中 */
self.onFulfilledCallBack.push(()=>setTimeout(()=>{
try {
let x = onFulfilled(self.value);
resolvePromise(promise2,x,resolve,reject)
} catch (error) {
reject(error)
}
}))
self.onRejectedCallBack.push(()=>setTimeout(()=>{
try {
let x = onRejected(self.reason);
resolvePromise(promise2,x,resolve,reject)
} catch (error) {
reject(error)
}
}))
}
})
return promise2;
}
/**處理在then函數中返回值*/
function resolvePromise(promise2,x,resolve,reject){
/**確保只執行一次*/
let used;
/**若是出現傳入的x==promise2 則會出現死循環,爲了爲了不這種狀況應該在這裏加一層判斷 */
if(x==promise2){
reject(new TypeError('Chaining cycle'));
}else if(x &&typeof x==='function'||typeof x==='object'){
try {
let then = x.then;
/**在這裏加上一層判斷是爲了不用戶傳入像{then:""}的對象*/
if(typeof then==='function'){
then.call(x,(y)=>{
if(used)return;
used=true;
resolvePromise(promise2, y, resolve, reject);
},e=>{
if(used)return;
used=true;
reject(e)
})
}else{
if(used)return;
used=true;
resolve(x)
}
} catch (error) {
reject(error)
}
}else{
x&&resolve(x)
}
}
module.exports=Promise
複製代碼
能夠參考這位大佬的文章
小邵教你玩轉promise函數