Callback Functions Double Executing? Dont Forget To return
Callback Functions Double Executing?
A quick example
function doSomething(err, result, final){
if(err){
final(err);
}
final(null,result);
}
Take the above as a simple way to express how you would have your final execute twice.
It may not be immediately apparent why the callback executes twice, consider the scenario below;
var match = 3;
(function(id, callback){
var interval = setInterval(function(){
var random = (Math.floor(Math.random() * 5) + 1);
if (random === id) {
var err = new Error("process terminated");
callback(err,{},final);
return false;
}
callback(null, { some: "data", id: id }, final);
}, 5000 );
})(match, doSomething);
Here we are matching a random number between 1 and 5 with a number stored in id
which was defined by var match
as 3. Our doSomething
callback is also provided as a callback in argument callback.
Every 5 sec we do this with a new random number (always the interval will call callback
) and for each iteration the callback
function is called either with an exception or some data to be processed.
Notice the return false after we call callback, consider the random number to be a killswitch.
Note: Previously I wrote about Node.js Error Handling Patterns, that the first argument for callbacks should always be the error.
The scenario ensures the callback is not executed twice when we encounter the killswitch (match the random number) because we only want to pass an instance of Error to the callback in-line with best node.js practice, not provide the callback doSomething
data to process when we match the killswitch.
When we have no match, we send some results to the callback as well as our final callback function which is expected to be executed once after each callback regardless if there was an Error (final can handle the Error).
As we saw in the begining, final
executes twice in doSomething
when there is an Error. Fixing the doSomething
is easy, just add a return false when there is an Error, just like our scenario.
function doSomething(err, result, final){
if(err){
final(err);
return false;
}
final(null,result);
return result;
}
And add a return to the callback also, to return the result.
Conclusion
A common mistake made by all early node developers is forgetting to return after a callback. While sometimes this has no implications, there are many times where you will run into odd issues or worse, debugging nightmares because your callback is being called twice.
Enjoyed this?
If you made it here I would love to hear what you thought of the article.