【问题标题】:Generators + Promises explanationGenerators + Promises 解释
【发布时间】:2018-08-17 02:19:57
【问题描述】:

我一直在研究 Promises 和 Generators,但我卡在了下面的脚本中:

function getFile(file) {
    return new Promise(function (resolve) {
        fakeAjax(file, resolve);
    });
}

function* getFiles() {
    var p1 = getFile('file1');
    var p2 = getFile('file2');
    var p3 = getFile('file3');

    output(yield p1);
    output(yield p2);
    output(yield p3);
}

function runner(gen) {
    var g = gen();
    function run(val) {
        val || undefined;
        var next = g.next(val);
        if(!next.done && !next.value !== undefined) {
            next.value
                .then(function(v) {
                    run(v);
                });
        }
    }
    run();
}

runner(getFiles);

我想弄清楚的是,当我在 getFiles 上获得第一个收益时会发生什么?为什么这段代码有效,我不明白。

*EDIT:输出只是一个console.log包装在一个函数中。 fakeAjax 函数根据请求的“文件”从对象返回文本。

【问题讨论】:

  • output 函数是什么? MDN 为生成器和 Promise 提供了出色的文档(不确定您不了解哪些) - 我建议阅读 MDN 上的文档 - 或 promisejs.org/generators

标签: javascript ecmascript-6 es6-promise


【解决方案1】:

我想弄清楚的是,当我在 getFiles 上获得第一个收益时会发生什么?为什么这段代码有效,我不明白。

yield 做了三件事:

  1. 它暂停生成器函数的执行
  2. 它定义了next() 的调用者将在value 属性中收到的值。在这种情况下,这就是您做出的承诺。
  3. 它可以选择充当表达式,并将值传递给next()。这将是您作为参数传递给next() 的文件名。

yield 就像一个双向管道,既接受值又传递值。

在您的第一个 yield 代码中,它将返回带有承诺的对象并暂停,但此时它不会将任何内容记录到控制台 - yield 可以暂停中间表达式。当您再次调用next() 时,它将完成console.log,然后移动到下一个yield。这可能会有点令人困惑,因为通常还有一个对next 的调用,而不是yields。例如,在这段代码中,`next 被调用了四次,这就是你得到最后一个 console.log 的原因。

这是一个MCVE,我假设它近似于您示例中的未定义函数:

function getFile(file) {
    return new Promise(resolve => setTimeout(() => resolve(file), 1000))
}

function* getFiles() {
    var p1 = getFile('file1');
    var p2 = getFile('file2');
    var p3 = getFile('file3');

    console.log(yield p1); // return promise, then pause, then log value passed to next()
    console.log(yield p2);
    console.log(yield p3);
}

function runner(gen) {
    var g = gen();
    function run(val) {
        var next = g.next(val);     
        if(!next.done && !next.value !== undefined) {
            next.value
                .then(function(v) {
                    run(v);
                });
        }     
    }
    run();
}

runner(getFiles);

【讨论】:

    猜你喜欢
    • 2019-01-08
    • 1970-01-01
    • 1970-01-01
    • 2014-05-30
    • 1970-01-01
    • 2014-06-26
    • 2018-12-15
    • 2019-01-14
    • 2015-07-31
    相关资源
    最近更新 更多