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

Max*_*ber 21 javascript for-loop yield generator ecmascript-6

使用ES6生成器,我看到如下代码:

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

是否有可能写下更像下面的代码?

var trivialGenerator = function *(array) {
    array.forEach(function *(item){
        yield item;
    });
};
Run Code Online (Sandbox Code Playgroud)

我问,因为经典for循环是令人厌恶的.

ale*_*ods 27

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

var trivialGenerator = function *(array) {
    for (var item of array) {
        // some item manipulation
        yield item;
    }
}
Run Code Online (Sandbox Code Playgroud)

for-of如果您对其中的项目进行了一些操作,则可以使用.否则,你绝对不需要创建这个装置中,由于array具有iterator界面本身.


小智 7

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

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

function *forEachGen(array, fn) { for (var i of array) yield *fn(i); }
Run Code Online (Sandbox Code Playgroud)

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

function *yieldSelf(item) { yield item; }
Run Code Online (Sandbox Code Playgroud)

forEachGen 将用作

yield *forEachGen(array, yieldSelf);
Run Code Online (Sandbox Code Playgroud)

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

function returnSelf(item) { return item; }
Run Code Online (Sandbox Code Playgroud)

然后就是

function *forEachGen(array, fn) { for (var i of array) yield fn(i); }
Run Code Online (Sandbox Code Playgroud)

用作

yield *forEachGen(array, returnSelf);
Run Code Online (Sandbox Code Playgroud)

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

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

然后做

yield *array.forEachGen(yieldSelf)
Run Code Online (Sandbox Code Playgroud)

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

async / await

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

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

async function returnSelf(item) { return await item; }
Run Code Online (Sandbox Code Playgroud)

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

async function forEachAsync(values, fn) {
  return await *values.map(returnSelf);
}
Run Code Online (Sandbox Code Playgroud)

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

forEachAsync([1,2,3], returnSelf) .
  then(result => console.log(result);
Run Code Online (Sandbox Code Playgroud)

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

(async function() { 
    console.log(await forEachAsync([1,2,3], returnSelf));
})();
Run Code Online (Sandbox Code Playgroud)

测试使用

babel-node --experimental test.js
Run Code Online (Sandbox Code Playgroud)