單個異步任務
var fetch = require('node-fetch');function* gen(){ var url = 'https://api.github.com/users/github'; var result = yield fetch(url); console.log(result.bio);}為了獲得最終的執行結果,你需要這樣做:
var g = gen();var result = g.next();result.value.then(function(data){ return data.json();}).then(function(data){ g.next(data);});首先執行 Generator 函數,獲取遍歷器對象。
然后使用 next 方法,執行異步任務的第一階段,即 fetch(url)。
注意,由于 fetch(url) 會返回一個 Promise 對象,所以 result 的值為:
{ value: Promise { <pending> }, done: false }最后我們為這個 Promise 對象添加一個 then 方法,先將其返回的數據格式化(data.json()),再調用 g.next,將獲得的數據傳進去,由此可以執行異步任務的第二階段,代碼執行完畢。
多個異步任務
上節我們只調用了一個接口,那如果我們調用了多個接口,使用了多個 yield,我們豈不是要在 then 函數中不斷的嵌套下去……
所以我們來看看執行多個異步任務的情況:
var fetch = require('node-fetch');function* gen() { var r1 = yield fetch('https://api.github.com/users/github'); var r2 = yield fetch('https://api.github.com/users/github/followers'); var r3 = yield fetch('https://api.github.com/users/github/repos'); console.log([r1.bio, r2[0].login, r3[0].full_name].join('/n'));}為了獲得最終的執行結果,你可能要寫成:
var g = gen();var result1 = g.next();result1.value.then(function(data){ return data.json();}).then(function(data){ return g.next(data).value;}).then(function(data){ return data.json();}).then(function(data){ return g.next(data).value}).then(function(data){ return data.json();}).then(function(data){ g.next(data)});但我知道你肯定不想寫成這樣……
其實,利用遞歸,我們可以這樣寫:
function run(gen) { var g = gen(); function next(data) { var result = g.next(data); if (result.done) return; result.value.then(function(data) { return data.json(); }).then(function(data) { next(data); }); } next();}run(gen);其中的關鍵就是 yield 的時候返回一個 Promise 對象,給這個 Promise 對象添加 then 方法,當異步操作成功時執行 then 中的 onFullfilled 函數,onFullfilled 函數中又去執行 g.next,從而讓 Generator 繼續執行,然后再返回一個 Promise,再在成功時執行 g.next,然后再返回……
啟動器函數
在 run 這個啟動器函數中,我們在 then 函數中將數據格式化 data.json(),但在更廣泛的情況下,比如 yield 直接跟一個 Promise,而非一個 fetch 函數返回的 Promise,因為沒有 json 方法,代碼就會報錯。所以為了更具備通用性,連同這個例子和啟動器,我們修改為:
新聞熱點
疑難解答
圖片精選