文章同步自我的博客:http://www.52cik.com/2016/07/11/generator-co.htmlhtml
此前只是簡單使用而沒有真正的去研究 Generator,此次要好好折騰下這貨。ajax
對於 jser 來講,異步很是熟悉了吧,可是真正理解異步的卻很少,由於大部分人只知道回調。
隨着js的快速發展,異步方案也層出不窮,從最開始的回調到Promise,再到Generator,而後到async/await。
甚至有人說 async/await 是異步的終極解決方案,我不敢直接贊同,只能說是目前最好的異步體驗。
本篇先從 Generator 講起,後序再詳細說 async/await。chrome
從最最經典的 ajax 請求開始今天的話題吧。
假如,咱們要依次請求 url1, url2, url3 這3個地址。編程
$.get('url1', function(r1) { $.get('url2', function(r2) { $.get('url3', function(r3) { console.log(r1, r2, r3); }); }); });
一不當心就寫成這樣了。
若是你是 jQuery 粉的話,你可能會說也能夠這樣實現啊。json
$.get('url1').then(function(r1) { console.log(r1); return $.get('url2'); }).then(function(r2) { console.log(r2); return $.get('url3'); }).then(function(r3) { console.log(r3); });
用 jQuery 的 Deferred 對象,相似 Promise 來規避回調地獄,看着確實平了,但體驗並非特別友好。api
Generator 的基礎這裏就不展開說了,直接說應用。瀏覽器
function* gen() { var r1 = yield $.get('url1'); var r2 = yield $.get('url2'); var r3 = yield $.get('url3'); console.log(r1, r2, r3); }
這是比較友好的異步方式,可是還有個相當重要的因素,怎麼運行這個 Generator 是個問題。
直接手動 g.next()
運行那確定不行,鬼知道有多少個 yield。
咱們要實現一個啓動器來運行它,並把 Promise 結果傳給下一次next,這樣就實現了 yield 接收值的功能。異步
先來實現一個最簡陋的起動器。async
function run(gen) { var g = gen(); function next(d) { var r = g.next(d); r.done || r.value.then(function(d){ next(d) }); // 這個是關鍵,把值傳回傳 } next(); }
而後咱們只要一行代碼。異步編程
run(gen);
Generator 就啓動起來了,而且一直執行到 done 爲 true 爲止。
打開 http://www.52tian.net/ 動漫網。非廣告,確實沒找到合適的測試站,湊合下吧。
而後把下面代碼貼到控制檯,看下結果。若是執行不了,請升級瀏覽器,本例在 chrome 51 下經過。
function* gen() { var r1 = yield $.get('/json/anime/4126.htm'); var r2 = yield $.get('/json/anime/11129.htm'); var r3 = yield $.get('/json/anime/427.htm'); console.log([r1, r2, r3].join('\n')); } function run(gen) { var g = gen(); function next(d) { var r = g.next(d); r.done || r.value.then(function(d){ next(d) }); // 這個是關鍵,把值傳回傳 } next(); } run(gen);
可能你已經發現了,其實這就是 co 的原理,但 co 比這個例子嚴謹多了,並且api設計的也很是友好。本篇到此也就結束了,利用 Generator 的 yield 功能實現參數回傳,讓代碼看起來很是‘同步’,讓異步體驗變的更加友好。