async.each() final callback is not executed - node.js

async.each(spiders, function(){
console.log('hi');
}, function(err) {
if(err) { console.log(err);}
else console.log('ok');
});
After logging 'hi', async didn't execute the callback and logged 'ok' or errors.
What is wrong in my code?

async provides two important parameters to your iterator function: an item and a callback. The first one gives you the actual data item from the array, and the second is a function, to indicate the end of the actual method. The final callback (the one with the log('ok')) gets called, when every iterator call indicated their own callback.
So your code should be something like this:
async.each(spiders, function(item, callback) {
console.log('spider: ' + item);
callback(null);
}, function(err) {
if (err) {
return console.log(err);
}
console.log('ok');
});
The null parameter means there is no error.
Also note, handling error like this, is a better practice.

Quoting from the async.each documentation:
iterator(item, callback) - A function to apply to each item in arr. The iterator is passed a callback(err) which must be called once it has completed. If no error has occurred, the callback should be run without arguments or with an explicit null argument.
Conclusion: You forgot to take the callback parameter and therefore did not call it either.

Related

Async.eachOfSeries not looping

I tried aysnc.eachOfSeries but the code does not loop. It stops executing in the first iteration itself and freezes. I guess I made some error in returning the callback.
I also tried putting a callback inside the else block but gives callback already called error.
This async.eachOfSeries is nested inside one more eachOfSeries.
async.eachOfSeries(data, function (value2, val, callback) {
let jsonObj = data[val];
let email = jsonObj.ToEmail;
jsonObj['retailer'] = res[camp].retailer;
jsonObj['summary'] = 'f';
let tempObj = {};
tempObj[id] = jsonObj;
let options = { new: true};
let campId = id;
User.addCampaignResponse(email, campId, tempObj, options, function (err, results) {
if (err) {
throw err;
} else {
console.log("gets printed once");
Campaign.updateResponse(_id, function (err, results2) {
if (err)
throw err;
else {
console.log("Gets printed once");
callback(); //tried this but gives callback already called error
}
}) // console.log(results);
}
})
}, function (err) {
console.log("Doesn't print");
callback();
})
You must use it like this:
//async.eachOfSeries(data, function (value2, val, callback) { => wrong
async.eachOfSeries(data, function (value2, callback) {
//
})
Thought I'd leave this here in case someone else hits this thread.
The problem is that on your optional callback at the end:
}, function (err) {
console.log("Doesn't print");
callback();
});
You're calling the iterator callback and not an outer callback.
In the context of your code you probably have your async inside other function which callback is the one you should call on your async's optional callback at the end. Or just don't use the optional function, but never let it go through your iterator callback after ending the loop.
You should also test for error, something like:
}, function(err){
if(err){
debug('Something went wrong in async: ' +err);
outerCallback(err, somethingIfitsthecase);
}else{
outerCallback(null, somethingIfitsthecase);
}
});
Check caolan's documentation as Parth Acharya recommended.
Thanks
Best regards
Pedro Velez Silva
It is supposed to work that way.
if an error occurs, which is happening in your case. It runs the final callback function that you've provided.
Link :- https://caolan.github.io/async/docs.html#eachOfSeries
A callback which is called when all iteratee functions have finished,
or an error occurs. Invoked with (err).
I had a similar dilemma and I solved it by adding a callback in the async param and calling it at the end of the method as shown below.
async.eachOfSeries(data, async (item, index, callback: any) => {
// method body
callback();
})

Node.js - Unable to use callback in if statement

Hi I am trying to execute a callback in a if statement but I get "TypeError: callback is not a function"
This is my code:
socket.on('authenticate', function (data, callback) {
// this works
callback("false");
// this doesn't work
if (data == "abc") {
callback("true");
}
});
Always check if callable function is passed, at least just do if(callback)
in Your problem there may be situation that clientside not waiting for callback (done emit call without passing callback argument).
Try this solution:
socket.on('authenticate', function (data, callback) {
console.debug('socket authenticate:', data); // for debug purposes
if (data == "abc") {
if(callback) { // callback may not be passed
callback(null, true); // keep in mind in callbacks first argument is error second is result
}
return; // return will prevent execution to go down, because most of times used for resulting call.
}
if(callback) { // callback may not be passed
callback("Not authenticated", false);
}
});

What is cb() in Node?

Where are people getting cb() from, is this a Node thing or vanilla JS thing?
For example:
Managing Node.js Callback Hell with Promises, Generators and Other Approaches
they're using cb() to I guess callback and return an error or a value or both in some cases depending on what the callback function sig is?
cb in the context you're describing it is how a vanilla callback function is passed into a (typically) asynchronous function, which is a common pattern in node.js (it's sometimes labelled next, but you can call it bananas if you so desire - it's just an argument).
Typically the first argument is an error object (often false - if all went as planned) and subsequent arguments are data of some form.
For example:
function myAsyncFunction(arg1, arg2, cb) {
// async things
cb(false, { data: 123 });
}
then using this function:
myAsyncFunction(10, 99, function onComplete(error, data) {
if (!error) {
// hooray, everything went as planned
} else {
// disaster - retry / respond with an error etc
}
});
Promises are an alternative to this design pattern where you would return a Promise object from myAsyncFunction
For example:
function myAsyncFunction2(arg1, arg2) {
return new Promise(function resolution(resolve, reject, {
// async things
resolve({ data: 123 });
});
}
then using this function:
myAsyncFunction2(10, 99)
.then(function onSuccess(data) {
// success - send a 200 code etc
})
.catch(function onError(error) {
// oh noes - 500
});
They're basically the same thing, just written slightly differently. Promises aren't supported especially widely in a native form, but if put through a transpiler (I'd recommend babel) during a build step they should perform reliably enough in a browser too.
Callbacks will always work in a browser with no shimming / transpilation.
node.js has lots of asynchronous operations that take a completion callback as an argument. This is very common in various node.js APIs.
The node.js convention for this callback is that the first argument passed to the callback is an error code. A falsey value for this first argument means that there is no error.
For example:
fs.readFile("test.txt", function(err, data) {
if (!err) {
console.log("file data is: " + data);
}
});
A function you create yourself may also define it's own callback in order to communicate the end of one or more asynchronous operations.
function getData(id, cb) {
var fname = "datafile-" + id + ".txt";
fs.readFile(fname, function(err, data) {
if (err) {
cb(err);
} else if (data.slice(0, 6) !== "Header"){
// proper header not found at beginning of file data
cb(new Error("Invalid header"));
} else {
cb(0, data);
}
});
}
// usage:
getData(29, function(err, data) {
if (!err) {
console.log(data);
}
});
From the Vanilla JS, you can declare a function and pass throuw parameters a declaration of another function, that can called async
https://developer.mozilla.org/en-US/docs/Glossary/Callback_function

async waterfall callback isn't called within mongoose save

I'm using express, mongoose, and async.
Within an update method on a controller, I'm calling the following:
//note: we're within a constructor's prototype method, hence the 'self'. also body is simply the request body.
async.waterfall([
function(callback) {
self.collection.findById(body._id).exec(function(err, item) {
if(item) {
callback(null, item);
} else {
callback(err);
}
});
},
function(item, callback) {
//callback(null, item); //makes this task work, but not what I need
//merge two together models together, then save
item.save( _.extend(item, body), function(err, item) {
console.log('code here never seems to get called within the waterfall');
callback(null, item);
});
}
], function(err, results) {
console.log('hello', err, results);
self.res.json(results);
});
So basically what I'm trying to do is find a document by id, then merge the new object in with the one I just found, save it, and return the result as JSON. But the callback function nested within the .save never seems to get called. So the entire request seems to hang and the final function in the waterfall never gets called.
I might be wrong, but it seems that the save method's callback gets called asynchronously. How would I go about getting this to work?
Side note: If the save method's callback is async, then why does this seem to work?
var _this = this;
var item = new this.collection(this.req.body);
item.save(function(err, data) {
_this.res.json(data);
});
That method returns the saved object as JSON just fine.
You are not using the Model.save method correctly. It just takes a callback as the first argument. You must fetch your item instance, then set your new property values on your item instance, then do item.save(callback);.

Should I be using process.nextTick

I'm trying to get my head around when to use process.nextTick. Below I'm using async library to control my code flow and was wondering if I should be calling nextTick in the end callback or not.
async.parallel([
function (callback) {
// do something
callback(data);
},
function (callback) {
// do something
callback(data);
}
],
// callback
function (data) {
process.nextTick(function () {
// do something
});
});
Without knowing exactly what your 'do something' is, I don't see any reason that you'd need to use nextTick in this situation. You use nextTick when you have reason to defer execution of a function to the next iteration of the event loop. You might want to read Understanding process.nextTick for more detail.
Also, note that async's parallel task completion callbacks take arguments err, data, so you should be doing:
async.parallel([
function (callback) {
// do something
callback(null, data);
},
function (callback) {
// do something
callback(null, data);
}
],
// callback
function (err, data) {
if (err) throw err;
// do something
});
The major difference being that the final callback is invoked immediately if one of the parallel tasks returns an error (calls callback with a truthy first argument).
My experience is that for async.parallel and other similar functions to work correctly, that you need to make all tasks definitely asynchronous; I love the async lib and it's my #1 choice over promises etc, but there can be some weird behavior if you don't force tasks to be async.
See here:
https://github.com/caolan/async#common-pitfalls-stackoverflow
so it should be:
async.parallel([
function(cb){
process.nextTick(function(){
doSomePotentiallySyncThing(cb);
});
},
function(cb){
process.nextTick(function(){
doSomePotentiallySyncThing(cb);
});
},
function(cb){
definitelyAsync(cb); // if it's **definitely** async, then we don't need process.nextTick
}
], function complete(err, results){
// we are in the final callback
});
I am 99% sure about this.

Resources