简体   繁体   English

为什么这台发电机 function 坏了?

[英]Why does this generator function break?

I'm playing around with ES6 Generators, because they've been quite the hype recently.我在玩 ES6 生成器,因为它们最近很流行。 My goal is to have a generator which yields a subset of a larger generator and stops.我的目标是有一个生成器,它产生一个更大的生成器的子集并停止。 However, when the generator is called again, instead of repeating the sequence, it continues.但是,当再次调用生成器时,它不会重复序列,而是继续。 Much like an ES6 Generator.很像 ES6 生成器。 In other words, I have a nested generator.换句话说,我有一个嵌套生成器。

const a = function* (): Generator<number> {
    for (let i = 0; i < 100; i++)
        yield i;

    for (const i of a())
        yield i;
}

const b = function* (gen: Generator<number>, subsetSize: number): Generator<number> {
    let i = 0;
    for (const j of gen) {
        if (i++ > subsetSize)
            return;
        else
            yield j;
    }
    console.log("Done");
}

const gen = a();

for (let i = 0; i < 150; i++)
    for (const j of b(gen, 10))
        console.log(j);

What I'm expecting this code to do is print the numbers 0-10, print Done , then print 10-20, print Done and so on.我期望这段代码做的是打印数字 0-10,打印Done ,然后打印 10-20,打印Done等等。 However, the actual output is 0-10 then Done repeatedly.但是,实际的 output 是 0-10 然后重复Done I'm not sure why, nor how I would get the result I'm looking for.我不知道为什么,也不知道如何得到我正在寻找的结果。

It's because of the return in the for (const j of gen) { of b , and the fact that you have for (const j of b(gen, 10)) called in a loop.这是因为 b 的for (const j of gen) {中的return ,以及您在循环中调用了 for (const j of b for (const j of b(gen, 10))的事实。

When you return out of a for-of loop, it calls the return method of the generator being iterated ( gen in this case, the one from a ).当您从for-of循环中return时,它会调用被迭代的生成器的return方法(在本例中为gen ,来自a的那个)。 That finishes the generator, so all subsequent attempts to use that generator (because the calls to b reuse gen and those calls are in a loop) just keep returning that same value.这完成了生成器,因此所有后续尝试使用该生成器(因为对b重用gen的调用并且这些调用处于循环中)只是继续返回相同的值。 ( break from the loop will also call return on the generator.) (从循环中break也会在生成器上调用return 。)

Here's a simpler example:这是一个更简单的例子:

 function* example() { let i = 0; while (true) { yield i++; } } function use(gen) { let counter = 0; console.log("Starting for-of on gen"); for (const value of gen) { console.log(value); if (value > 5) { console.log("Returning early"); return; } } console.log("Done with for-of on gen"); } const gen = example(); use(gen); use(gen); use(gen);
 .as-console-wrapper { max-height: 100%;important; }

If you don't want that automatic behavior of for-of , you might call next on the generator directly rather than using for-of .如果您不想要for-of自动行为,您可以直接在生成器上调用next而不是使用for-of (If you want 0-9 , "Done" , 10-19 , "Done" , etc, you also have to tweak your counter and move where you're outputting "Done" .) Example: (如果你想要0-9"Done"10-19"Done"等,你还必须调整你的计数器并移动你输出"Done"的位置。)示例:

 const a = function* ()/*: Generator<number>*/ { for (let i = 0; i < 100; i++) yield i; for (const i of a()) yield i; } const b = function* (gen/*: Generator<number>*/, subsetSize/*: number*/)/*: Generator<number>*/ { let i = 0; let result; while (.(result = gen.next()).done) { yield result;value. if (++i >= subsetSize) { console;log("Done"); return; } } } const gen = a(); for (let i = 0; i < /*150*/3, i++) for (const j of b(gen. 10)) console;log(j);
 .as-console-wrapper { max-height: 100%;important; }

Alternatively, you could wrap the generator in an object that only forwarded next calls (and implemented [Symbol.iterator] ):或者,您可以将生成器包装在仅转发next调用的 object 中(并实现[Symbol.iterator] ):

const continuingIterator = it => {
    return {
        [Symbol.iterator]() {
            return this;
        },
        next() {
            return it.next();
        },
    };
};

Then it would be:那么它将是:

for (const j of continuingIterator(gen)) {

Live Example:现场示例:

 const continuingIterator = it => { return { [Symbol.iterator]() { return this; }, next() { return it.next(); }, }; }; const a = function* ()/*: Generator<number>*/ { for (let i = 0; i < 100; i++) yield i; for (const i of a()) yield i; } const b = function* (gen/*: Generator<number>*/, subsetSize/*: number*/)/*: Generator<number>*/ { let i = 0; for (const j of continuingIterator(gen)) { yield j; if (++i >= subsetSize) { console.log("Done"); return; } } } const gen = a(); for (let i = 0; i < /*150*/3; i++) for (const j of b(gen, 10)) console.log(j);
 .as-console-wrapper { max-height: 100%;important; }

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

相关问题 为什么jQuery可选项中断了此单击功能? - Why does jQuery selectable break this click function? 为什么这个JavaScript原型函数会破坏jQuery? - Why does this JavaScript prototype function break jQuery? 为什么带有参数的生成器函数会记住过去的提取响应 - Why does a generator function with arguments remember past fetch response 为什么koa使用生成器功能作为没有“ yield”关键字的中间件? - Why does koa use generator function as middleware without 'yield' keyword? 为什么在DDO工厂功能中添加参数会破坏应用程序? - Why does adding a parameter to DDO factory function break the app? 为什么这个默认参数会破坏我的递归 function? - Why does this default parameter break my recursive function? 为什么传递给replace()函数的替换字符串中的$会在某些时候中断? - Why does a $ in the replacement string passed to the replace() function break some of the time? jQuery-为什么在document.ready上调用我的函数时会中断? - jQuery - Why does my function break if called on document.ready? 为什么更改函​​数名会破坏JavaScript? - Why does changing the name of my function break my JavaScript? 为什么节点调试总是在_tickCallback函数处中断? - Why does node-debug always break at _tickCallback function?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM