【问题标题】:Coroutine example协程示例
【发布时间】:2018-10-07 20:36:01
【问题描述】:

在学习 JavaScript 中的协程时,我无法理解以下example

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 将在此时此刻返回一个包含所有帖子的 Promise。因此,这将是doNext 的第一次运行。

doNext 的第二次运行将在生成器函数在let comments = yield Promise.all(promises); 行停止执行时开始;将控制权交还给coroutine 函数。此时此刻,next.value.then(doNext) 对我来说不再有意义。我希望next.value 是能够解决 cmets 的 Promise。

即,Promises.all(promises) 由生成器函数传回。因此,一旦 post Promises 获取了所有 cmets,这应该会解决。

显然,我没有正确看到这一点,因为我给出的解释与调用的实际执行不符。我看错了什么?

【问题讨论】:

    标签: javascript generator es6-promise coroutine


    【解决方案1】:

    也许它有助于扩展递归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)
      });
    });
    

    【讨论】:

    • 所以,在第二次调用 next 时,next.valuePromise.all(promises)。也就是说,在您的代码中出现的两次next.value.then 中,第二次的计算结果为Promise.all(promises)但由于posts 变量被传递给生成器,由gen.next(data),它被分配给comments 变量;因为要传递给gen.next 的第二个值代替了生成器中的第二个yield。 看来这是代码中的错误; comments 变量应该由Promise.all(comments) 的实现值填充,而不是由posts 填充。
    • @MusséRedi 否。要传递给gen.next() 的第二个值代替了第一个 yield,要传递给gen.next() 的第三个值取代第二个yield。我已经更新澄清。
    猜你喜欢
    • 1970-01-01
    • 2018-09-13
    • 1970-01-01
    • 1970-01-01
    • 2020-01-13
    • 2022-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多