![](/img/trans.png)
[英]How to convert Node.js async streaming callback into an async generator?
[英]How can I convert this async callback to a generator?
我很難理解發電機。 但我認為我想做的應該是可能的。
我有一個可以訪問Page
的對象Topic
。 最初實現Topic
是為了通過回調來檢索Page
。
var Topic = function( id ) {
var repository = new PageRepository();
this.id = id;
this.getAllPages = function( callback ) {
repository.getAllPagesByTopicId( this.id, function( result ) {
var pages = [];
while( result.hasNext() ) {
pages.push( result.next() );
}
callback( pages );
} );
}
}
var topic = new Topic( 1 );
topic.getAllPages( function( pages ) {
console.log( pages ) // received Page instances
} );
現在,假設我無法重構PageRepository
的回調機制,但我確實希望重構Topic
,以便可以通過生成器而不是通過回調來訪問它的頁面。 在沒有太多草草的情況下,這是否可行?
我知道我可以使用for...of
語句來迭代生成器值,例如:
var topic = new Topic( 1 );
for( let page of topic.pages() ) { // create the generator
console.log( page ); // received next Page
}
...所以我想到了以下內容:
var Topic = function( id ) {
...
this.pages = function*() { // refactored getAllPages () to a generator function pages()
repository.getAllPagesByTopicId( this.id, function( result ) {
while( result.hasNext() ) {
yield result.next(); // yield the next Page
}
} );
}
}
但是,這不起作用,可能是因為在回調內部調用了yield
。
然后,基於我對本文的 (較差的)理解(從“要使用生成器...”開始),我認為這可能有效:
var Topic = function( id ) {
...
this.pages = function*() {
let gen = function*() {}(); // create an inner generator
// not actually sure why the following wrapper function is needed
// but something similar is used in mentioned article
yield function() {
repository.getAllPagesByTopicId( this.id, function( result ) {
while( result.hasNext() ) {
gen.next( result.next() ); // call next() on inner generator
}
} );
}(); // immediately create this mysterious wrapper function
}
}
不幸的是,但這也不起作用。
因此,這就是我試圖實現的目標,而沒有太多麻煩; 含義:沒有模塊(例如co,suspend等)和/或卷積的thunk生成器,您呢?
我確實希望重構
Topic
,以便可以通過生成器而不是通過回調來訪問它的頁面。 這樣做沒有太多麻煩嗎?
不,不是。 您在這里混合了兩個概念:
result
迭代器 一旦第二個概念有了自己的關鍵字( async
/ await
),就有一些想法可以合並這兩個概念 ,但這還不適用( 異步迭代建議在第3階段)。 您將陷入“嵌套”結構,即異步回調內部的類似於數組的迭代器。
因此,您可以為任何一個使用生成器,但不能同時使用兩者。 這是否值得懷疑。 請注意,這兩者都不會使您的代碼同步,因此您在某些方面始終必須使用異步回調。
使用生成器實例而不是數組進行回調:
function Topic( id ) {
var repository = new PageRepository();
this.id = id;
this.getAllPages = function( callback ) {
repository.getAllPagesByTopicId( this.id, function( result ) {
callback( function* () {
while( result.hasNext() ) {
yield result.next();
}
}() );
} );
}
}
var topic = new Topic( 1 );
topic.getAllPages( function( pageiterator ) {
for( let page of pageiterator ) {
console.log( page ); // received next Page
}
} );
不要回調函數,而是恢復生成器(如最簡單的異步示例):
function Topic( id ) {
var repository = new PageRepository();
this.id = id;
this.getAllPages = function( it ) {
repository.getAllPagesByTopicId( this.id, function( result ) {
for (var pages = [], result.hasNext(); ) pages.push( result.next() );
it.next( pages );
} );
}
}
var it = (function *() {
var topic = new Topic( 1 );
var pages = yield topic.getAllPages( it );
console.log( pages ) // received Page instances
}());
it.next();
是的,您可以同時使用這兩種方法(將生成器創建的迭代器傳遞到異步生成器的next
方法中),但這可能很令人困惑。 他們將保持獨立的發電機。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.