首先我們先看一下promise是如何使用的:
通過promise構建出來的物件有三種狀態,pending(進行中),fulfilled(已成功),rejected(已失敗)
狀態只能由 pending 變為 fulfilled 或由 pending 變為 rejected ,且狀態改變之後不會在發生變化,會一直保持這個狀態。
通過then函式註冊成功或者失敗函式,promise內部呼叫resolve或者reject呼叫對應的函式。
; (function ()class customepromise
func(this._resolve.bind(this), this._reject.bind(this));
}_resolve(val)
_reject(val)
}window.customepromise = customepromise;
})();
首先我們定義了乙個customepromise的類,通過window暴露出去,通過前面promise呼叫我們可以看到引數是乙個函式,該函式接受兩個引數,resolve,reject,通過呼叫兩個函式來執行對應的成功或者失敗函式。第一步,我們在內部首先要判斷傳入是否為乙個函式,才進行下一步操作。
; (function ()class customepromise
try
catch (err)
}_resolve(val)
_reject(val)
}window.customepromise = customepromise;
})();
promise最大的好處就是他的捕獲機制,一旦你在外部函式吃錯都可以在內部可以捕獲到,這樣你外面的指令碼還能繼續往下執行,並通過失敗函式可以列印出來。
一開始我們在建構函式開始執行的時候儲存了這個物件狀態為pending,然後在這個promise物件上掛載了兩個屬性用來儲存成功和失敗函式。下面我們來實現then函式
then(resolvefunc, rejectfunc)}
通過判斷promise物件來決定函式是否執行,如果處於pending狀態,就把成功失敗函式存入對應的陣列,如果狀態已經改變,就執行對應的函式。下面實現成功失敗函式的**。
_resolve(val) )}, 0)
}_reject(val) )
}, 0)
}
注意下我們的promise屬於微任務,他會讓我們主線程的任務先執行,所以我們這裡採用非同步模擬。但這裡還是存在乙個問題,就是我們可以在外部多次呼叫,這明顯是不允許,所以我們來優化下**。
_resolve(val)this.value=val;
this._status = status[1];
this.resolvearr.foreach(item => )
}, 0)
}_reject(val)
this.value=val;
this._status = status[2];
this.rejectarr.foreach(item => )
}, 0)
}
用過jquery的同學都知道jquery是可以鏈式呼叫,同樣我們的promise也是可以的,那就表示我們的then函式返回值同樣也是個promise物件,下面我們來改寫then函式。
then(resolvefunc, rejectfunc)rejectfunc = function (val)
switch (_this._status)
})}
注意這裡並不好理解,因為之前我們存入的事成功和失敗函式,這裡我們包裝了乙個函式並把then函式返回值promise物件的resolve函式也存入進去,這就表示如果我們第乙個promise狀態改變會接著觸發第二個promise物件的執行,但需要注意如果我們函式的返回值同樣是乙個promise物件的話,我們必要要等待其狀態改變才能觸發他的下乙個的then函式,這是乙個難點,很不好理解,我們使用過把then函式返回的promise物件的resolve時間掛在函式內部的then上面,一旦內部函式狀態改變會觸發then函式的對應的事件,當然我們也是要加上容錯處理,下面附上**:
then(resolvefunc, rejectfunc)else
else }}
catch (err)
}rejectfunc = function (val)
else
else }}
catch (err)
}switch (_this._status)
})}
最後說一下resolve()引數如果是乙個promise物件的話,必須要等待引數的狀態改變才能觸發他的then函式,原理跟上面的很相似。
_resolve(val) )})return;
}if (this._status != status[0])
this._status = status[1];
this.resolvearr.foreach(item => )
}, 0)
}_reject(val) )
})return;
}if (this._status != status[0])
this._status = status[2];
this.rejectarr.foreach(item => )
}, 0)
}
最後附上所有的**:
; (function ()class customepromise
try
catch (err)
}_resolve(val) )
})return;
}if (this._status != status[0])
this._status = status[1];
this.resolvearr.foreach(item => )
}, 0)
}_reject(val) )
})return;
}if (this._status != status[0])
this._status = status[2];
this.rejectarr.foreach(item => )
}, 0)
}then(resolvefunc, rejectfunc)
else
else }}
catch (err)
}rejectfunc = function (val)
else
else }}
catch (err)
}switch (_this._status) })}
}window.customepromise = customepromise;
})();
手寫簡易版Promise
在完成符合 promise a 規範的 之前,我們可以先來實現乙個簡易版promise,因為在面試中,如果你能實現出乙個簡易版的promise基本可以過關了。那麼我們先來搭建構建函式的大體框架 const pending pending const resolved resolved const r...
簡易版Vue響應式流程原始碼實現
1 使用 new vue vhtml vhtml methods changeobject 2 需要實現 class vue 屬性 proxy data set v 需實現 響應式處理 class observer else walk data object.keys data foreach ke...
簡易版redux實現
redux其實只有幾個重要的api,getstate,subscribe和dispatch,getstate用來獲取狀態,subscribe監聽狀態的改變,dispatch派發事件改變狀態,下面就來看下。首先是createstore,它接收三個引數,分別是reducer函式,初始狀態值,還有就是中介...