異步編程系列教程:node
回顧一下咱們以前學習的promise。咱們巧妙利用了promise/deferred
模式,用鏈式結構代替了嵌套回調的結構,大大緩解了回調地獄。咱們再來看看以前咱們舉的那個異步串行隊列的例子吧!假設咱們有一個hello.txt
,裏面存了一個JSON文件的文件名,咱們須要獲得JSON文件的message屬性的值。步驟以下:git
hello.txt
文件這個例子咱們以前也是舉過很是屢次的,咱們嘗試使用Promise鏈式結構完成:github
//這裏的readFile已是promise化的異步API readFile('hello.txt', 'utf-8') .then(function(filename){ return readFile(filename, 'utf-8'); }) .then(JSON.parse) .then(function(data){ console.log(data.message); }) .catch(function(err){ console.error(err.message); });
這樣一看下來,promise好像並無多大問題,思惟是線性的,並且錯誤處理也很友好。咱們只須要把上一層執行後的結果經過then()
傳到下一步執行便可。嗯,但不得不說被鏈式結構束縛後,咱們並無獲得一種酣暢淋漓的編程體驗。編程
咱們要寫的爽,固然是要將異步編程獲得同步編程的體驗,這樣咱們直接使用同步API看一下是怎樣的:json
var filename = fs.readFileSync('hello.txt', 'utf-8'); var json = fs.readFileSync(filename, 'utf-8'); console.log(JSON.parse(json).message);
同步的寫法清晰明瞭,並且更符合咱們以往的編程習慣。可是同步API阻塞代碼這個弊病會在Javascript的單線程執行中很是明顯。咱們到底有沒有一種既能夠很是接近同步編程的寫法,又能夠異步不阻塞代碼執行呢?既然問出這種問題,答案固然是有的,就是今天的主角:Generator。api
Generator,顧名思義是一個構造器,它自己是用來生成迭代器的。它是ES6的新東西,因此你爲了使用它,須要在node中開啓harmony模式才能體驗到它。promise
$ node --harmony
異步
基於Generator,TJ大神作了一個co
庫。co
在最新的版本里,結合Generator和Promise改善了異步編程的體驗,也就是咱們以前說的:既能夠同步,又不會阻塞。異步編程
仍是同樣的例子,咱們結合promise的代碼和同步API的代碼對比看看:函數
co(function* (){ var filename = yield readFile('hello.txt', 'utf-8'); var json = yield readFile(filename, 'utf-8'); return JSON.parse(json).message; }).then(console.log, console.error);
很是像有沒有,咱們再也不須要將每一次異步的結果都放在then()
中進行處理,咱們能夠經過相似於同步的寫法調用Promise異步API,大大提高編程體驗。最後co()
返回了一個promise對象,提供咱們作最後的數據處理和錯誤處理。咱們從同步API轉到co
,僅僅須要作到如下幾點:
function*
。這也就是Generator函數yield
標識符return
出來,在then()
中進行處理便可咱們在舉完異步串行的例子後,此次的文章就接近尾聲了。最後咱們能夠大體瞭解一下co
究竟是如何運做的呢?咱們會在接下來的文章進行深究,這一次就簡單說一說,你看成預習就能夠了:
next()
指令啓動。{value: AnyType, done: Boolean}
對象,value
是此次執行的結果,done
是迭代是否結束。並等待下一次的next()
指令。next()
再次啓動後。若done
屬性不爲true,則能夠繼續從上一次中止的地方繼續迭代。done
爲true。yield
後面跟的必須是一個promise化的異步API,因此next()
獲得的結果是一個promise對象。co
會自動爲該異步promise對象的resolve
中,增添一個next()
。經過前面的異步執行完回調後,再調用next()
,使迭代器的代碼不斷向前執行。resolve
。或許如今你們看的是隻知其一;不知其二,或許很興奮想知道更多相關的。若僅僅是想學會用co,我想上面的大概已經足夠你看了。可是想更深刻,你必須先弄懂promise的原理和Generator的相關特性。最後使用co
庫必定會駕輕就熟。
接下來,我會先講一些關於Generator的相關特性,再配合以前說過的promise,深刻到co
的源碼學習中。