讓 Generator 自啓動

文章同步自我的博客: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 來和諧回調

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 功能實現參數回傳,讓代碼看起來很是‘同步’,讓異步體驗變的更加友好。

相關文章
相關標籤/搜索