【问题标题】:Why does this generator skip a yield outside the try block?为什么这个生成器会在 try 块之外跳过一个 yield?
【发布时间】:2016-08-19 19:35:07
【问题描述】:

背景

我正在试验Generator.prototype.throw() 的工作原理并制作了这个例子:

var myGen = function *() {

    try{
        yield 1;
        yield 2;
        yield 3;
        yield 4;
        yield 5;
    }

    catch(err) {

        console.log(err);
    }

    yield 7;
    yield 8;
    yield 9;

}

var myIterator = myGen();

console.log(myIterator.next());
console.log(myIterator.next());
console.log(myIterator.next());

myIterator.throw(new Error('Bullocks!'));

console.log(myIterator.next());
console.log(myIterator.next());
console.log(myIterator.next());

在运行时会产生以下结果:

{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: false }
[Error: Bullocks!]
{ value: 8, done: false }
{ value: 9, done: false }
{ value: undefined, done: true }

问题

我可以理解yield 4try块的剩余部分在抛出错误后被跳过。

但是为什么生成器会跳过yield 7

【问题讨论】:

    标签: javascript ecmascript-6 generator


    【解决方案1】:

    它不会跳过yield 7。当您调用throw() 时,控制流进入catch 块,记录错误,然后继续执行,直到下一个yield 返回一个新的迭代器结果对象{ value: 7, done: false }

    只是在你的代码中你没有console.log 这个特定的结果对象。试试:

    console.log(myIterator.throw(new Error('Bullocks!')));
    

    这在step 11 and 13 of the spec中有解释:

    1. 使用 abruptCompletion 恢复 genContext 的暂停评估,作为暂停它的操作的结果。令result为恢复计算返回的完成记录。
    2. (…)
    3. 返回完成(结果)。

    【讨论】:

    • 谢谢。所以.throw() 语句实际上就像.next() 语句一样工作在导致生成器产生下一个yield 语句的值....?
    • 没错。它通过在其中抛出错误的附加特殊效果来恢复生成器。恢复的动作和next()一样:恢复到下一个yield,并返回一个新的迭代器结果对象{value, done}
    • 谢谢。作为 Mozilla 的员工:在 Mozilla 中对 Generator.prototype.throw() 的解释可能还有一点改进的余地 - 否则很好 - 文档.... :) 它没有说明任何关于返回对象的内容。我实际上认为.throw 声明只是关于“投掷”......
    • 好建议。我编辑了 MDN 文档:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…。以后随时自行更新;这是一个维基! :)
    • 好的 - 不知道 :) 谢谢你这样做。
    猜你喜欢
    • 2016-12-02
    • 1970-01-01
    • 2019-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-03
    • 1970-01-01
    • 2011-02-22
    相关资源
    最近更新 更多