在学习JavaScript中的协同机制时,我无法理解下面的示例
coroutine(function* () {
let posts = yield fetchPosts();
let promises = posts.map(post => fetchComments(post));
let comments = yield Promise.all(promises);
displayComments(comments);
})
function coroutine(fn) {
let gen = fn();
let doNext = (data) => {
let next = gen.next(data);
if (!next.done) {
return next.value.then(doNext);
}
};
doNext();
}在我看来,在上面的示例中调用coroutine时,doNext将累计被调用两次。
当调用coroutine时,生成器函数在其第一行let posts = yield fetchposts();上停止执行;控件被传递回coroutine函数。在let next = gen.next(data);行,控制被传递回生成器函数。
现在,据我所知,fetchposts将在这个时候返回一个包含所有帖子的承诺。因此,这将是doNext的第一次运行。
doNext的第二次运行将在生成器函数在行let comments = yield Promise.all(promises);停止执行时开始;将控制权返回给coroutine函数。在这个时刻,next.value.then(doNext)对我来说不再有意义了。我希望next.value是能够解决这些评论的承诺。
也就是说,Promises.all(promises)是通过生成器函数传回的。因此,一旦所有评论都由post承诺获取,这个问题就应该得到解决。
显然,我没有正确地看到这一点,因为我给出的解释不符合调用的实际执行。我看错什么了?
发布于 2018-04-29 21:13:12
也许它有助于扩展递归的doNext函数来可视化执行流程:
function* fn() {
let posts = yield fetchPosts();
let promises = posts.map(post => fetchComments(post));
let comments = yield Promise.all(promises);
displayComments(comments);
}
let gen = fn();
let data;
let next = gen.next(data); // data is undefined
// generator runs until first yield
// next.value becomes fetchPosts()
// assert(!next.done)
next.value.then(data => {
let next = gen.next(data); // data is result of fetchPosts()
// generator runs until second yield:
// posts becomes passed value (data)
// promises becomes posts.map(…)
// next.value becomes Promise.all(…)
// assert(!next.done)
next.value.then(data => {
let next = gen.next(data); // data is result of Promise.all(…)
// generator runs until the end:
// comments becomes passed value (data)
// comments are logged
// next.value becomes undefined
// assert(next.done)
});
});https://stackoverflow.com/questions/50054932
复制相似问题