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
Can I yield from an inner function?
提问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 for
loop is an abomination.
我问是因为经典for
循环令人厌恶。
回答by alexpods
No, you can't use yield
inside of the inner function. But in your case you don't need it. You can always use for-of
loop instead of forEach
method. It will look much prettier, and you can use continue
, break
, yield
inside it:
不,您不能yield
在内部函数内部使用。但在你的情况下,你不需要它。您始终可以使用for-of
循环而不是forEach
方法。它看起来更漂亮,你可以使用continue
,break
,yield
它里面:
var trivialGenerator = function *(array) {
for (var item of array) {
// some item manipulation
yield item;
}
}
You can use for-of
if you have some manipulations with item inside it. Otherwise you absolutely don't need to create this generator, as array
has iterator
interfacenatively.
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 forEach
with the equivalent of *
, or, if the callback itself is a generator, to tell forEach
to 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; }
forEachGen
would 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 forEach
on 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; }
forEachAsync
maps 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