I'm using Koa.js framework and Mongoose.js module.
Normally to get a result from MongoDB I code like this:
var res = yield db.collection.findOne({id: 'my-id-here'}).exec();
But I need to execute this line for every element of an array named 'items'.
items.forEach(function(item) {
var res = yield db.collection.findOne({id: item.id}).exec();
console.log(res) // undefined
});
But this code doesn't run as yield is in the function. If I write this:
items.forEach(function *(item) {
var res = yield db.collection.findOne({id: item.id}).exec();
console.log(res) // undefined
});
I'm not getting the result in res variable either. I tried to use 'generator-foreach' module but that didn't worked like this.
I know that this is my lack of knowledge about the language literacy of Node.js. But can you guys help me finding a way how to do this?
Generators are function executions that can be suspended and resumed at a later point. Generators are useful when carrying out concepts such as 'lazy execution'. This basically means that by suspending execution and resuming at will, we are able to pull values only when we need to.
forEach “executes a provided function once per array element.” Array. map “creates a new array with the results of calling a provided function on every element in this array.”
map() is chainable, and can pass its new array to another chained method. forEach() is not chainable.
The main difference between map and forEach is that the map method returns a new array by applying the callback function on each element of an array, while the forEach method doesn't return anything. You can use the forEach method to mutate the source array, but this isn't really the way it's meant to be used.
You can yield
arrays, so just map your async promises in another map
var fetchedItems = yield items.map((item) => {
return db.collection.findOne({id: item.id});
});
The accepted answer is wrong, there is no need to use a library, an array is already an iterable.
This is an old question, but since it has no correct answer yet and it appears on the first page on google search for the key terms "iterators and forEach" I will respond the question:
There is no need to iterate over an array, since an array already conforms to the iterable API.
inside your generator just use "yield* array" (note the * ) yield* expression is used to delegate to another generator or iterable object
Example:
let arr = [2, 3, 4];
function* g2() {
yield 1;
yield* arr;
yield 5;
}
var iterator = g2();
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: 4, done: false }
console.log(iterator.next()); // { value: 5, done: false }
console.log(iterator.next()); // { value: undefined, done: true }
For examples and in depth information visit: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/yield*
Thanks guys, I've done this using the 'CO' module. Thanks.
var co = require('co');
items.forEach(co(function* (item) {
var img = yield db.collection.findOne({id: item.id}).exec();
}));
EDIT: With the latest version of CO, you need co.wrap() for this to work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With