JavaScript:嵌套在生成器内部的函数中使用yield

25

这段代码会产生一个错误:

function *giveNumbers() {
    [1, 2, 3].forEach(function(item) {
        yield item;
    })
}

这可能是因为yield语句在一个不是生成器的函数中。有没有更优雅的方法来解决这个问题?我是指除了以下方法:

function *giveNumbers() {
    let list = [1, 2, 3];
    for (let i = 0; i < list.length; i++) {
        yield list[i];
    }
}
4个回答

13
这可能是因为yield在一个非生成器函数中。是的,你不能从回调函数中使用yield。
有一种优雅的方式来克服这个问题吗?这取决于用例。通常没有任何理由真正想要从回调函数中使用yield。
在你的情况下,你需要一个for…of循环,它在几乎每个方面都优于.forEach: almost every aspect
function *giveNumbers() {
    for (let item of [1, 2, 3])
        yield item;
}

3
然而我认为 forEach 应该在 ES6 中被删除。 - Bergi
4
对于那些不懂拉丁语(像我一样)或者太懒得用谷歌翻译的人来说:“forEach在ES6中肯定会被淘汰”。 - Palisand
1
@Palisand 此外,我认为 forEach 应该在 ES6 中被淘汰 - Bergi
@Palisand 承认,至少我是这个意思,我的拉丁语有点生疏,而且我不知道“a ES6”是否是正确的选择。 - Bergi
1
@Bergi - “没有任何理由想要从回调函数中进行yield”- 原因是将异步代码变成同步。为什么?为了让它看起来更好。有没有某种绕过方式来实现这一点? - fider
显示剩余3条评论

5
您可以使用yield *语法。
function *giveNumbers() {
    yield * [1, 2, 3].map(function(item) {
        return item;
    })
}

1
这不会向父级作用域屈服 - shabunc

1

yield将结果返回给调用者。
假设forEach回调是一个生成器(在那里设置一个自定义生成器不是问题)- 这意味着当回调yield结果时,它会将其返回到forEach

基本上,在你的问题中,你试图做的是:

callback -> yields to forEach -> yields to giveNumbers -> yields to caller

因此,forEach 应该将结果返回给 giveNumbers。但是由于 forEach 不起作用,如果不重新定义具有自定义 forEach 的原型数组,则不可能实现。

实际上,你的第二个片段才是最优雅的开始。

0

你也可以使用 while 并像这样传递参数 (演示)

function *giveNumbers(array, start) {
    var index = start || 0;
    while(array.length > index + 1) {
        yield array[index++];
    }
    return array[index];
}


var g = giveNumbers([1,2,3], 0);

var finished = false;

while(!finished) {
    var next = g.next();
    console.log(next.value);
    if(next.done) {
        finished = true;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接