天天看點

《JavaScript應用程式設計》一一2.18 Promises與Deferreds

本節書摘來華章計算機出版社《javascript應用程式設計》一書中的第2章,第2.18節,作者:eric elliott 更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視。

promises作為一個對象,維護着成功與失敗兩個回調函數隊列。與在異步/同步操作結束後執行的回調函數有所不同,你可以在異步操作的結尾處傳回一個包含了一組回調函數的promises。

promises能夠讓你了解目前異步操作的進行狀态,是在等待中,還是已完成,具體完成進度是多少。在整個過程中随時都可以向promises中添加新的回調函數,當異步操作結束時,promises會被正确解析,此時辨別為成功的回調函數隊列會被批量執行。

受commonjs規範promises/a的啟發,jquery實作了promises并将這一規範推廣至了javascript社群。jquery使用promises管理自己内部(包括ajax請求在内)的異步任務隊列,事實上,早在jquery1.5中,所有ajax方法執行後均會傳回一個promises,來看看它是如何工作的。

這個例子展示了,使用ajax請求去擷取“programming javascript applications”頁面的中繼資料,因為所有jquery中的ajax輔助函數都會傳回一個promises,是以,你可以在whendatafetched.done()中追加你的成功回調函數。

promises與回調函數間的差別在于,promises是調用者傳回的一個對象,而不是傳入調用者随後被執行的一個函數。promises對象支援在異步操作過程中随時添加新的回調函數,并且會将回調函數彼此間的代碼邏輯隔離開,是以使用promises時回調函數并不一定要在異步操作開始前就傳入。

deferred對象包含了一組方法,它被用來管理控制promises。jquery的deferred()方法傳回了一個與promises功能極為類似的對象,這個對象上還擁有resolve()與reject()方法,這兩個方法可以觸發相應隊列中的回調函數。假設你出于靈活性的考慮,想對現有的settimeout()方法做改造,你想讓它随時都可以接受回調函數的傳入,而并不是僅能在首次定時調用時添加回調,你可以使用deferred對象來實作這個改造。

promises特别适用于那些有着一系列複雜調用序列的異步操作,因為往往在發起新的資料請求之前必須完成對多個資料源的請求。

回調函數會使得代碼嵌套邏輯變得越來越深,但擁有了promises,我們可以在任意數量的promises對象被解析之後再決定下一步操作,下面是新timer()函數的應用:

繼續閱讀