Promise的實現機制(一)
阿新 • • 發佈:2019-01-31
開發過程非同步請求很常見,但是回撥地獄我們還是可以去避免的,這篇文章就不再贅述Promise的具體使用方法,而是探尋一下它的實現機制。首先是一個簡單的Promise的例子:
function getInfo(){
return new Promise(function(reslve,reject){
http.get(url,function(result){
reslove(reslut.id)
})
})
}
getInfo().then(function(id){...})
開始的時候最大的疑惑是:.then()的操作怎麼就知道我的非同步請求成功了?其實內部的原理就是在一個promise的例項裡面的then方法註冊我所有非同步請求成功後的回撥,而後通過reslove方法將非同步請求結果返回,也就是將之前註冊的非同步回撥一一執行,大概的實現程式碼就是:
function Promise(fn){
var value = null
var callbacks = [] //非同步回撥的陣列
this.then(function(callbackDone){
callbacks.push(callbackDone) // 將所有的非同步回撥放入陣列
return this //支援鏈式呼叫
})
function reslove(value){
callbacks.forEach(function(callback){
callback(value) // 遍歷執行非同步回撥
})
}
fn(reslove)
}
描述起來就是我們在new Promise()的時候,傳入的函式執行非同步請求,將非同步請求的回撥通過呼叫.then()方法將回調註冊入callbacks裡,非同步請求成功之後執行reslove(result)的方法,將非同步回撥全部執行。這就是一個Promise最基礎版本的實現,那目前的問題就是不能讓reslove的方法先於then方法執行,那我們能想到最簡單的方法就是加入定時器的延時處理:
function Promise(fn){
var value = null
var callbacks = [] //非同步回撥的陣列
this.then(function(callbackDone) {
callbacks.push(callbackDone) // 將所有的非同步回撥放入陣列
return this //支援鏈式呼叫
})
setTimeout(function(){
// 延時處理
function reslove(value){
callbacks.forEach(function(callback){
callback(value) // 遍歷執行非同步回撥
})
}
},0)
fn(reslove)
而接下來就是考慮狀態機制的問題了,我們都知道Promise的三個狀態:pending,fulfilled,rejected。而且只能是由pending變為fulfilled或rejected且狀態不可逆,也就是狀態一旦改變就不會再次改變了,那我們將程式碼稍微改動下:
function Promise(fn){
var value = null
var callbacks = [] //非同步回撥的陣列
var status = 'pending'
this.then(function(callbackDone){
if(status === 'pending'){
callbacks.push(callbackDone) // 將所有的非同步回撥放入陣列
}
callbackDone(value)
return this //支援鏈式呼叫
})
setTimeout(function(){
// 延時處理
function reslove(newValue){
var value = newValue
status = 'fulfilled'
callbacks.forEach(function(callback){
callback(value) // 遍歷執行非同步回撥
})
}
},0)
fn(reslove)
其實以上就是Promise實現的核心程式碼,後續還會涉及到異常處理和鏈式Promise,我也需要更進一步的學習,不過目前也是已經瞭解到Promise內部實現的機制是怎樣的,也很有助於我平常使用的時候更好的理解它。那後期會再更一版Promise的實現機制(二),對於異常處理和鏈式Promise再進行一些探討