发电机+承诺说明

时间:2018-08-17 02:19:58

标签: javascript ecmascript-6 es6-promise

我一直在研究Promises and 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函数根据请求的“文件”从对象返回文本。

1 个答案:

答案 0 :(得分: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);