繁体   English   中英

使用yield / generator了解代码流

[英]Understanding code flow with yield/generators

我已经阅读了使用JavaScript生成器( 例如this)的几个代码示例。 我可以想到的最简单的生成器使用块是:

function read(path) {
    return function (done) {
        fs.readFile(path, "file", done);
    }
}

co(function *() {
    console.log( yield read("file") );
})();

确实确实打印出了file的内容,但是我的挂断称为done 貌似,yield是语法糖,用于将其返回的内容包装在回调中并适当地分配结果值(至少在co的情况下,将error参数抛出给回调)。 我对语法的理解正确吗?

使用yield done看起来像什么?

看起来,yield是语法糖,用于将其返回的内容包装在回调中并适当地分配结果值(至少在使用co的情况下,将error参数抛出给回调)

不, yield不是语法糖。 这是生成器的核心语法元素。 实例化该生成器后,可以运行它(通过在其上调用.next() ),它将返回return ed或yield ed的值。 当发电机是yield版,您可以在以后通过调用继续它.next()一次。 next的参数将是yield表达式在生成器内部返回的值。

在使用co情况下, 按照您认为在异步控制流库中自然的方式“适当地”处理那些异步回调事物(和其他事物 )。

使用收益率后,看起来像什么?

您阅读文章中thread函数示例给您带来了良好的印象:

function thread(fn) {
  var gen = fn();
  function next(err, res) {
    var ret = gen.next(res);
    if (ret.done) return;
    ret.value(next);
  }
  next();
}

在您的代码中, yield会在运行时从生成器中产生表达式read("file")的值。 这就是ret.val ,它是gen.next()的结果。 对此, next函数传递-回调,将继续与发电机res ULT传递给它。 在生成器代码中, yield表达式似乎返回了该值。

发生的事情的“展开”版本可以这样写:

function fn*() {
    console.log( yield function (done) {
        fs.readFile("filepath", "file", done);
    } );
}
var gen = fn();
var ret1 = gen.next();
var callasync = ret1.value;
callasync(function next(err, res) {
    var ret2 = gen.next(res); // this now does log the value
    ret2.done; // true now
});

我在这里发布了有关发电机如何工作的详细说明。

以简化形式,您的代码可能看起来像这样,不带co (未经测试):

function workAsync(fileName)
{
    // async logic
    var worker = (function* () {

        function read(path) {
            return function (done) {
                fs.readFile(path, "file", done);
            }
        }

        console.log(yield read(fileName));
    })();

    // driver
    function nextStep(err, result) {
        try {
            var item = err? 
                worker.throw(err):
                worker.next(result);
            if (item.done)
                return;
            item.value(nextStep);
        }
        catch(ex) {
            console.log(ex.message);
            return;
        }
    }

    // first step
    nextStep();
}

workAsync("file");

workAsync的驱动程序部分通过调用nextStep()异步迭代生成器对象。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM