javascript 我可以从内部函数屈服吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29313604/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 10:22:28  来源:igfitidea点击:

Can I yield from an inner function?

javascriptfor-loopgeneratoryieldecmascript-6

提问by Max Heiber

With ES6 generators, I see code like this:

使用 ES6 生成器,我看到这样的代码:

var trivialGenerator = function *(array) {
    var i,item;
    for(var i=0; i < array.length; i++){
        item = array[i];
        yield item;
    };
};

Is it possible to write something more like the code below instead?

是否可以编写更类似于以下代码的内容?

var trivialGenerator = function *(array) {
    array.forEach(function *(item){
        yield item;
    });
};

I'm asking because the classic forloop is an abomination.

我问是因为经典for循环令人厌恶。

回答by alexpods

No, you can't use yieldinside of the inner function. But in your case you don't need it. You can always use for-ofloop instead of forEachmethod. It will look much prettier, and you can use continue, break, yieldinside it:

不,您不能yield在内部函数内部使用。但在你的情况下,你不需要它。您始终可以使用for-of循环而不是forEach方法。它看起来更漂亮,你可以使用continuebreakyield它里面:

var trivialGenerator = function *(array) {
    for (var item of array) {
        // some item manipulation
        yield item;
    }
}

You can use for-ofif you have some manipulations with item inside it. Otherwise you absolutely don't need to create this generator, as arrayhas iteratorinterfacenatively.

for-of如果您对其中的 item 进行了一些操作,则可以使用。否则你绝对不需要创建这个生成器,因为array它本身就有iterator接口

回答by Max Heiber

No, you can't yield from a callback (technically, it's not an "inner function", which means something else). There's obviously no way to call forEachwith the equivalent of *, or, if the callback itself is a generator, to tell forEachto invoke the callback with yield *.

不,您不能从回调中屈服(从技术上讲,它不是“内部函数”,这意味着其他东西)。显然没有办法forEach用 的等价物来调用*,或者,如果回调本身是一个生成器,就告诉用forEach来调用回调yield *

One alternative is to write a function forEachGen, as follows:

一种替代方法是编写一个函数forEachGen,如下所示:

function *forEachGen(array, fn) { for (var i of array) yield *fn(i); }

essentially moving the for-loop into forEachGen. Defining a little sample generator as

基本上将 for 循环移动到forEachGen. 将一个小样本生成器定义为

function *yieldSelf(item) { yield item; }

forEachGenwould be used as

forEachGen将用作

yield *forEachGen(array, yieldSelf);

This assumes the callback is a generator itself, as you seem to imply you want in your example. If the callback were a ROF (regular old function), such as

这假设回调本身是一个生成器,正如您在示例中暗示的那样。如果回调是 ROF(常规旧函数),例如

function returnSelf(item) { return item; }

Then it would be

然后就是

function *forEachGen(array, fn) { for (var i of array) yield fn(i); }

used as

用作

yield *forEachGen(array, returnSelf);

If you don't mind adding this to the array prototype, then

如果您不介意将其添加到数组原型中,那么

Object.defineProperty(Array.prototype, 'forEachGen', { value :
    function *(fn) { for (i of this) yield fn(i); }
});

then do

然后做

yield *array.forEachGen(yieldSelf)

You may be interested in http://fitzgen.github.io/wu.js/, which defines a wrapper for generators with methods such as forEachon the wrapper.

您可能对http://fitzgen.github.io/wu.js/感兴趣,它为生成器定义了一个包装器,其中包含诸如包装器上的方法forEach

async/ await

async/ await

With await, you should be able to do the following.

使用await,您应该能够执行以下操作。

Define a trivial callback which just returns a promise for itself.

定义一个简单的回调,它只为自己返回一个承诺。

async function returnSelf(item) { return await item; }

forEachAsyncmaps the input array into an array of promises, and uses await *to create and return a promise for all the individual promises being ready.

forEachAsync将输入数组映射到一个承诺数组,并用于await *为所有准备好的个人承诺创建和返回一个承诺。

async function forEachAsync(values, fn) {
  return await *values.map(returnSelf);
}

We can treat the result as a regular promise and print it out in a then:

我们可以将结果视为常规承诺并将其打印出来then

forEachAsync([1,2,3], returnSelf) .
  then(result => console.log(result);

or use a little IIFE async wrapper to do wait for the result and then print it out:

或者使用一个小的 IIFE 异步包装器来等待结果然后打印出来:

(async function() { 
    console.log(await forEachAsync([1,2,3], returnSelf));
})();

Tested using

测试使用

babel-node --experimental test.js