我已經讀過ECMAScript 6附帶的並且已經在node.js dev版本中可用的生成器,可以更輕鬆地以同步方式編寫異步代碼。但是我很難理解,我們如何使用生成器來編寫異步代碼?我們如何使用生成器以同步方式編寫異步代碼?
回答
我們首先必須記住,使用ES生成器,我們可以將值傳遞給next()
方法,該方法將成爲生成器中yield語句的返回值。
的想法是給發電機的一種控制器的功能。
發電機,每一個我們稱爲異步函數的時候,我們yield
,所以我們回饋控制,控制器功能。當異步操作完成時,控制器功能只會調用next()
。在此期間,我們可以處理其他事件,因此它是非阻塞的。
例無發電機:
// chain of callbacks
function findAuthorOfArticleOfComment (commentID, callback) {
database.comments.find({id: commentID}
, function (err, comment) {
if (err) return callback(err);
database.articles.find({ id: comment.articleID }
, function (err, article) {
if (err) return callback(err);
database.users.find({ id: article.authorID }
, function (err, author) {
if (err) return callback(err);
callback(author);
});
});
});
}
findAuthorOfArticleOfComment (commentID, function(err, author) {
if(!err) console.log(author);
}
例如用發電機:
我們必須使用,如果你想使用它,這將控制流量,像suspend或bluebird庫承諾。爲了更好的理解,我將舉一個沒有圖書館的例子。
function* myGenerator(resume, commentID, callback) {
var comment, article, author;
comment = yield database.comments.find({id: commentID}, resume);
article = yield database.articles.find({id: comment.articleID}, resume);
author = yield database.users.find({id: article.authorID}, resume);
};
// in real life we use a library for this !
var findAuthorOfArticleOfComment = function(commentID, callback) {
var resume, theGenerator;
resume = function (err, result) {
var next;
if(err) return callback(err);
next = theGenerator.next(result);
if (next.done) callback(null, result);
}
theGenerator = myGenerator(resume, commentID, callback);
theGenerator.next();
}
// still the same function as first example !
findAuthorOfArticleOfComment (commentID, function(err, author) {
if(!err) console.log(author);
}
我們做什麼:
- 創建發電機,給人一種恢復功能作爲第一個參數,通過函數調用
- 呼叫
next()
第一次給出的參數。我們的第一個異步功能已經達到並且發電機產量。每次resume
函數被調用 - ,我們得到的值,並把它傳遞給下一個,所以在生成代碼繼續執行和產量的語句返回正確的值。
在現實生活中,我們將使用庫,並將生成器作爲參數傳遞給通用控制器函數。所以我們必須寫的是生成器,如果使用Promise(帶有Promise兼容庫),則可以使用value = yield asyncFunction(parameters, resumeCallback);
或value = yield functionReturningPromise(parameters);
。以同步的方式編寫異步代碼是一種非常好的方法。
最佳來源:
http://tobyho.com/2013/06/16/what-are-generators/
http://jlongster.com/A-Closer-Look-at-Generators-Without-Promises
你爲什麼要用發電機的'resume'回調?它看起來有點醜陋。我們不能像同步代碼一樣返回嗎? – Bergi
這個例子儘可能簡單地理解它如何在沒有魔法的情況下工作。大多數時候你會使用藍鳥這樣的庫,它支持Promises。在這種情況下,你確實會產生一個承諾,藍鳥會在承諾解決時調用next()。但是如果你只是在沒有使用Promises的情況下返回,這將是同步並因此阻止代碼,它將失去所有興趣。本身的收益不會增加任何異步魔法,它只會停止生成器的執行。所以如果你想要更多的「魔法」,並使用回報而不是回叫,你最好檢查藍鳥。 – Guilro
我知道(我使用的承諾的話),我只是認爲有可能是一個更好的模式來得到結果出來'myGenerator'的(不出來異步'findAuthorOfArticleOfComment',當然) – Bergi
補全Guilro的回答,發生器可以這樣寫:
controllerFunction(function*() {
yield functionThatReturnsAThenable()
yield anotherFunctionThatReturnsAThenable()
return;
});
控制器功能所做的是調用發電機,從收益中獲得任何回報,將next()
撥打then()
直到發電機爲done
。
事情是這樣的:
function controllerFunction(generator) {
function run(runnableGenerator) {
var result = runnableGenerator.next(); // or send(params)
if (!result.done) {
if (result.value.then) {
result.value.then(function() {
run(runnableGenerator);
});
} else {
run(runnableGenerator);
}
}
}
var runnableGenerator = generator();
run(runnableGenerator);
}
- 1. 以編程方式將同步代碼轉換爲異步代碼
- 2. 如何使用SVN使我們的代碼同步?
- 3. 將異步扭曲代碼集成到同步Python代碼中
- 4. 合同異步和同步代碼
- 5. 如何在我的項目中編寫異步代碼
- 6. 異步生成器不是迭代器?
- 7. 我們可以同步字符串生成器嗎?
- 8. 在異步中寫入新代碼但調用同步
- 9. 如何使用$ .getJSON編寫異步?
- 10. 如何強制C#異步操作以...同步方式運行?
- 11. 以異步方式異步創建BitmapFrame
- 12. 如何編寫異步JavaScript方法?
- 13. 如何編寫異步方法?
- 14. 我可以使用此代碼的新異步/等待方法
- 15. 執行異步代碼同步
- 16. 讓eval同步運行異步代碼
- 17. 同步MeteorJS異步代碼Meteor.methods函數
- 18. 異步代碼中需要的同步
- 19. 如何運行代碼以異步方式在jQuery Mobile的
- 20. 使同步代碼取決於異步代碼
- 21. 如何使異步調用同步
- 22. 如何使異步調用同步
- 23. 代碼合同和異步
- 24. 從Finagle的同步代碼調用異步/未來代碼
- 25. 使用GCD /異步代碼:
- 26. 如何同步異步方法?
- 27. 爲什麼基於生成器的協程消耗異步生成器異步數據生成器以及協程異步數據使用者?
- 28. 如何編寫通用代碼以向Rest服務進行異步調用
- 29. 以異步代碼排序
- 30. 替代方式寫XHR同步行爲
那麼,爲什麼你要問,如果你已經知道答案嗎? – vkurchatkin
http://stackoverflow.com/help/self-answer – Guilro
[嘗試理解node.js中的生成器/ yield - 執行異步函數的原因?](http://stackoverflow.com/questions/17516952/試圖理解生成器 - 在節點中生成yield-in-js-what-executed-the-asynchron) – vkurchatkin