【问题标题】:How to conditionally stop a JavaScript generator?如何有条件地停止 JavaScript 生成器?
【发布时间】:2017-10-04 10:12:32
【问题描述】:

使用如下迭代器:

function* idMaker(){
    let index = 0;
    while(index < 3)
        yield index++;
}

如何确保根据条件提前停止生成器?

function* idMaker(){
    let index = 0;
    while(index < 3)
        if (checker(index))
            yield index++;
        else
            return;
}

在生成器中使用是否合适?我应该使用 break 而不是 yield break 可能就像在 C# 中一样吗?

您能否提供一个指向 MDN 或讨论该问题的规范的链接?

【问题讨论】:

  • 任何终止函数的东西都会起作用。我认为没有任何最佳实践。

标签: javascript c# iterator generator


【解决方案1】:

您是否尝试过查看生成器的return 方法?

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/return

function* gen() { 
  yield 1;
  yield 2;
  yield 3;
}

const g = gen();

g.next();        // { value: 1, done: false }
g.return('foo'); // { value: "foo", done: true }
g.next();        // { value: undefined, done: true }
g.return('bar'); // { value: "bar", done: true }

【讨论】:

  • 我特别关心 yield 语法及其在生成器实现中的等价物,以便摆脱它。
  • 你是否想过像往常一样在生成器内部使用yield,获取对生成器的引用,然后停止生成器从外部检查条件并调用return?
  • 这是一个很好的建议,但我正在寻找库使用,因此生成器不需要将任何责任推到调用站点。
  • 哦,好的。您是否尝试使用 this 引用在内部调用它?在你停止你的条件内调用 this.return()
  • 因为真正遵循标准应该使用自身的return方法来停止执行,而不是break或任何其他技巧
【解决方案2】:

我决定使用以下代码进行实验验证:

function checker(i) {
  return i !== 2;
}

function* idMakerReturn(){
    let index = 0;
    while(index < 3)
        if (checker(index))
            yield index++;
        else
            return;
}

function* idMakerBreak(){
    let index = 0;
    while(index < 3)
        if (checker(index))
            yield index++;
        else
            break;
}

const a = idMakerReturn();
console.log('1', a.next());
console.log('2', a.next());
console.log('3', a.next());

const b = idMakerBreak();
console.log('1', b.next());
console.log('2', b.next());
console.log('3', b.next());

两种变体在从中分离时都正确返回{ "done": true, "value": undefined }。我还通过观察推断的函数类型使用 TypeScript 进行了检查。

function* idGen(seed: string | undefined) {
  if (!seed) {
    return; // Or `break`
  }

  const something = seed.trim();
}

使用return,一切正常,函数返回类型为IterableIterator&lt;T&gt;

对于break,我被要求提供一个标签以跳转到,并且something 不再被推断为可以安全访问(只是string,因为undefinedif 处理),但仍然是string | undefined

这使我得出结论,正如 Felix 所说,终止生成器函数的任何操作都将正确生成 done: true 项,但似乎 return 更可取,因为转义分析适用于它,而它不适用于 @ 987654334@.

目前还没有找到官方的说法,但对我来说已经足够了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-29
    • 2021-02-27
    • 2020-04-01
    • 1970-01-01
    • 2020-12-06
    • 1970-01-01
    • 2012-04-06
    相关资源
    最近更新 更多