我很难理解发电机。但我认为我应该做的事情应该是可能的。
我有一个可以访问Topic
的对象Page
。最初实现了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
。
然后,根据我对this article(来自"使用生成器......"以后)的(差)理解,我认为这可能有效:
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生成器以及你有什么?
答案 0 :(得分:3)
我确实想重构
Topic
,以便我可以通过生成器访问它的页面,而不是通过回调。这是可行的,没有太多的麻烦吗?
不,不是真的。你在这里混合了两个概念:
result
迭代器一旦第二个获得了自己的关键字async
/ await
),就有merge the two concepts的想法,但这还不适用(async iteration proposal在阶段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
方法),但这可能非常令人困惑。而且他们会留下独立的发电机。