Looping Array and checking MongoDB collection in a loop (Async)
I have a bit of a problem with some asynchronous loop with mongodb calls. I tried several approaches and looked into libraries like async and co-monk. (I am using monk as my connection, etc.).
I have an array of data that I need to pass to a mongo collection to check it is ok, etc. My background is PHP / Sql, so the asynchronous nature of the mango makes my head a little difficult.
Some basic sudo code of what I'm trying to do:
function check (collection) {
var records = { { body: "Test 1"}, { body: "Test 2" } };
for (var i in records) {
collection.find({ body: records[i].body }, {}, function (e, rows) {
console.log(rows);
});
}
}
It only runs on the last write cycle. I know this has to do with the asynchronous nature of JS, but how can I structure it properly to work?
Thank,
source to share
A common key to asynchronous processing is that you want to have some indication of when the current iteration is in progress before moving on to the next iteration. Since actual operations such as the ones .find()
here themselves use a "callback" that is "called" when the operation is complete with a response, what you usually want to do is call what ends the iteration in the same section of code.
Basically, you can get the same result as you can in traditional loops by using the "async.eachSeries" method , which just happens "one iteration at a time":
function check (collection) {
var records = [ { body: "Test 1"}, { body: "Test 2" } ];
async.eachSeries(records,function(item,callback) {
collection.find( item, function (err, rows) {
console.log(rows);
callback(err)
});
},function(err) {
if (err) throw err;
console.log("done");
});
}
So, each array argument is passed to the "iterator" function here as an "item" parameter, and the second argument is a "callback" function that will be used later. Each time the iterator is called, this argument is passed to the method .find()
, which in turn has its own "callback" where the "error" or "docs" response is provided.
Within this callback, the "callback" provided by the "iterator" function is then called to signal the end of the current iteration. This allows "each" function to continue and actually call the next "iteration" and process the next element in the array.
When noting your background, remember the correct way to denote an "array" in JavaScript with parentheses []
, as shown. This is usually an important difference when working with arrays.
There are other variants of "async.each" and "async.eachLimit" that allow some degree of parallelism at the same time, but the Series method does things "in order" in a way that you are used to traditional loops.
So, when the operations for a loop are "non-blocking", you need to indicate when that loop is complete before you want to move on.
source to share