深入掌握 ECMAScript 6 非同步程式設計(三):co函式庫的含義與用法

發表於2015-10-14

以下是《深入掌握 ECMAScript 6 非同步程式設計》系列文章的第三篇。

一、什麼是 co 函式庫?

co 函式庫是著名程式設計師 TJ Holowaychuk 於2013年6月釋出的一個小工具,用於 Generator 函式的自動執行。

比如,有一個 Generator 函式,用於依次讀取兩個檔案。

co 函式庫可以讓你不用編寫 Generator 函式的執行器。

上面程式碼中,Generator 函式只要傳入 co 函式,就會自動執行。

co 函式返回一個 Promise 物件,因此可以用 then 方法新增回撥函式。

上面程式碼中,等到 Generator 函式執行結束,就會輸出一行提示。

二、 co 函式庫的原理

為什麼 co 可以自動執行 Generator 函式?

前面文章說過,Generator 函式就是一個非同步操作的容器。它的自動執行需要一種機制,當非同步操作有了結果,能夠自動交回執行權。

兩種方法可以做到這一點。

(1)回撥函式。將非同步操作包裝成 Thunk 函式,在回撥函式裡面交回執行權。

(2)Promise 物件。將非同步操作包裝成 Promise 物件,用 then 方法交回執行權。

co 函式庫其實就是將兩種自動執行器(Thunk 函式和 Promise 物件),包裝成一個庫。使用 co 的前提條件是,Generator 函式的 yield 命令後面,只能是 Thunk 函式或 Promise 物件。

上一篇文章已經介紹了基於 Thunk 函式的自動執行器。下面來看,基於 Promise 物件的自動執行器。這是理解 co 函式庫必須的。

三、基於 Promise 物件的自動執行

還是沿用上面的例子。首先,把 fs 模組的 readFile 方法包裝成一個 Promise 物件。

然後,手動執行上面的 Generator 函式。

手動執行其實就是用 then 方法,層層新增回撥函式。理解了這一點,就可以寫出一個自動執行器。

上面程式碼中,只要 Generator 函式還沒執行到最後一步,next 函式就呼叫自身,以此實現自動執行。

四、co 函式庫的原始碼

co 就是上面那個自動執行器的擴充套件,它的原始碼只有幾十行,非常簡單。

首先,co 函式接受 Generator 函式作為引數,返回一個 Promise 物件。

在返回的 Promise 物件裡面,co 先檢查引數 gen 是否為 Generator 函式。如果是,就執行該函式,得到一個內部指標物件;如果不是就返回,並將 Promise 物件的狀態改為 resolved 。

接著,co 將 Generator 函式的內部指標物件的 next 方法,包裝成 onFulefilled 函式。這主要是為了能夠捕捉丟擲的錯誤。

最後,就是關鍵的 next 函式,它會反覆呼叫自身。

上面程式碼中,next 函式的內部程式碼,一共只有四行命令。

第一行,檢查當前是否為 Generator 函式的最後一步,如果是就返回。

第二行,確保每一步的返回值,是 Promise 物件。

第三行,使用 then 方法,為返回值加上回撥函式,然後通過 onFulfilled 函式再次呼叫 next 函式。

第四行,在引數不符合要求的情況下(引數非 Thunk 函式和 Promise 物件),將 Promise 物件的狀態改為 rejected,從而終止執行。

五、併發的非同步操作

co 支援併發的非同步操作,即允許某些操作同時進行,等到它們全部完成,才進行下一步。

這時,要把併發的操作都放在陣列或物件裡面。

相關文章