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 *
.
One alternative is to write a function forEachGen
, as follows:
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
function *yieldSelf(item) { yield item; }
forEachGen
would be used as
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
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.
async
/ await
With await
, you should be able to do the following.
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.
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
:
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:
(async function() {
console.log(await forEachAsync([1,2,3], returnSelf));
})();
Tested using
babel-node --experimental test.js