簡易版promise原始碼實現

2022-08-28 09:33:12 字數 3551 閱讀 7982

首先我們先看一下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函式,初始狀態值,還有就是中介...