Is the following node.js code blocking or non-blocking? - node.js

I have the node.js code running on a server and would like to know if it is blocking or not. It is kind of similar to this:
function addUserIfNoneExists(name, callback) {
userAccounts.findOne({name:name}, function(err, obj) {
if (obj) {
callback('user exists');
} else {
// Add the user 'name' to DB and run the callback when done.
// This is non-blocking to here.
user = addUser(name, callback)
// Do something heavy, doesn't matter when this completes.
// Is this part blocking?
doSomeHeavyWork(user);
}
});
};
Once addUser completes the doSomeHeavyWork function is run and eventually places something back into the database. It does not matter how long this function takes, but it should not block other events on the server.
With that, is it possible to test if node.js code ends up blocking or not?

Generally, if it reaches out to another service, like a database or a webservice, then it is non-blocking and you'll need to have some sort of callback. However, any function will block until something (even if nothing) is returned...
If the doSomeHeavyWork function is non-blocking, then it's likely that whatever library you're using will allow for some sort of callback. So you could write the function to accept a callback like so:
var doSomHeavyWork = function(user, callback) {
callTheNonBlockingStuff(function(error, whatever) { // Whatever that is it likely takes a callback which returns an error (in case something bad happened) and possible a "whatever" which is what you're looking to get or something.
if (error) {
console.log('There was an error!!!!');
console.log(error);
callback(error, null); //Call callback with error
}
callback(null, whatever); //Call callback with object you're hoping to get back.
});
return; //This line will most likely run before the callback gets called which makes it a non-blocking (asynchronous) function. Which is why you need the callback.
};

You should avoid in any part of your Node.js code synchronous blocks which don't call system or I/O operations and which computation takes long time (in computer meaning), e.g iterating over big arrays. Instead move this type of code to the separate worker or divide it to smaller synchronous pieces using process.nextTick(). You can find explanation for process.nextTick() here but read all comments too.

Related

How Nodejs knows if sync or async

I understand what a callback is and what asynchronous means, what I don't get is how to run asynchronous functions in node.
For example, how is this
var action = (function(data,callback) {
result = data+1;
callback(result);
});
http.createServer(function (req, res) {
action(5, function(r){
res.end(r.toString());
});
}).listen(80);
different from this
var action = (function(data) {
result = data+1;
return result;
});
http.createServer(function (req, res) {
var r = action(5);
res.end(r.toString());
}).listen(80);
?
I guess in the first example I'm doing it asynchronously, yet I don't know how Node knows when to do it sync or async... is it a matter of the return? or the fact that in the sync mode we're doing var x = func(data);?
And also: when to use sync or async? Because obviously you don't want to use it when adding +1... is it OK to use async just when performing IO tasks, such as reading from DB?
For example, I'm using the library crypto to encrypt a short string (50 chars at most), is this case a good example where I should already be using async?
I guess in the first example I'm doing it asynchronously...
Your first example isn't async :) Merely passing a callback and calling it when you're done doesn't make a function asynchronous.
Asynchronous means that, basically, you're telling Node: "here, do this for me, and let me know when you're done while I continue doing other stuff".
Your example is not handing anything to Node for future completion. It's doing a calculation and calling the callback immediately after that. That's functionally the same as your second example, where you return the result of the calculation.
However, you can change your first example to something that is asynchronous:
var action = (function(data,callback) {
setTimeout(function() {
result = data + 1;
callback(result);
}, 1000);
});
Here, you're telling Node to delay calling the callback for one second, by using setTimeout. In the mean time, Node won't get stuck waiting for a second; it will happily accept more HTTP requests, and each one will be delayed one second before the response is sent.
When to use sync or async?
Asynchronous code is "viral": if you rely on functions that are async, your own code that uses those functions will also have to be async (generally by accepting a callback, or using another mechanism to deal with asynchronicity, like promises).
For example, I'm using the library crypto to encrypt a short string (50 chars at most), is this case a good example where I should already be using async?
This depends on which function you're using. AFAIK, most encryption functions in crypto aren't asynchronous, so you can't "make" them asynchronous yourself.
Both examples will work synchronous. Simple async operations are setTimout and setInterval.
Node actually doesn't care what code are you running. You can block or not (blocking/non-blocking).
In other words - you have event loop. If your process is async he will pass the program control to the event loop, so it can execute any other action node needs to be done. If not - he wont.
if you want a function to work asynchronously, you can do that using promises, look at the code below :
function is_asynch(){
return new Promise((resolve,reject)=>{
resolve( here_your_synch_function() )
})
}

fake async function. Why?

I was reading this article on howtonode,
but don't get why it's fake async ?
So fake async is described as:
function asyncFake(data, callback) {
if(data === 'foo') callback(true);
else callback(false);
}
asyncFake('bar', function(result) {
// this callback is actually called synchronously!
});
Correct code: always async
function asyncReal(data, callback) {
process.nextTick(function() {
callback(data === 'foo');
});
}
My question is what's wrong with the first part of code ?
Why nextTick() can promise the 'right' effect ?...
Please explain to me. Thanks.
Nothing's wrong with the first case. However, it's just that you have to be proactive (as the developer) to know exactly what's happening in your code.
In the first case, you are not doing any I/O, and the callback is not actually being put into the Event Loop. It just the same as doing this:
if(data === 'foo')
return true;
else
return false;
However, in second case, you are putting the callback into the event loop until the next iteration.
In terms of how things work, nothing's wrong. However, you need to be aware of what implications are.
For instance:
function maybeSync(a, cb) {
if(a === 'a') {
cb('maybeSync called');
} else {
// put the called into event-loop for the next iteration
process.nextTick(function() {
cb('maybeSync called');
});
}
}
function definitelySync() {
console.log('definitelySync called');
}
someAsync('a', function(out) {
console.log(out);
});
definitelySync();
In the top case, which one gets called first?
If the input is "a" then the output is:
maybeSync called
definitelySync called
If the input is something else (e.g. not "a") then the output would be:
definitelySync called
maybeSync called
You need to make them consistent, as it would be easy to distinguish if the callback can be called sync/async based on the condition. Again comes back to being responsible, being consistent and being aware of what's happening in your code. =)
In the async fake function - you can see that callback is called as a normal function invocation i.e in the same call stack.
someone calls async fake fn
async fake fn calls the callback passed to it
If that callback takes time to complete - the async fake fn is kept waiting i.e it remains in call stack.
By using process tick - we are just submitting the callback function to be scheduled for execution.
This process tick call completes immediately and the asyncreal will return immediately. Thus the callback will be executed in asynchronous way.

Is it bad practice to emit events with callbacks as arguments in node?

Is it bad practice to emit events with callbacks as arguments in node?
var someonesListened = self.emit('doSomething', param, callback);
if (!someonesListened) {
callback();
}
// in another module somewhere
this.on('doSomething', function(param, callback) {
// Something async....
// Then sometime later
callback();
})
EDIT: After writing this question I realised that by providing a continuation callback to an event that can be intercepted by multiple listeners defeats the purpose so I don't think I will be taking this approach.
No, it's not a bad practice if you know what are you doing.
But keep in mind that this callback could be called multiple times, or not called at all depending on how many listeners there are. If you're fine with that, by all means use callbacks.
I'm having to try and read between the lines, but it appears that you have the following requirements:
You have a callback that needs to run exactly once.
If no one else invokes the callback, you need to do it yourself, but...
...someone else may invoke that callback asynchronously.
Assuming that this is the case, you could use an approach like this:
// define a callback that will exit early if it has already been invoked,
// AND will invoke itself after a 10 second delay, if no one else has.
var hasRun = false, timeoutId = setTimeout(callback, 10000);
function callback() {
if (hasRun) return;
hasRun = true;
clearTimeout(timeoutId);
// do something cool
}
self.emit('some-event', callback);
But, of course, I may have completely misread your requirements :)

Block function whilst waiting for response

I've got a NodeJS app i'm building (using Sails, but i guess that's irrelevant).
In my action, i have a number of requests to other services, datasources etc that i need to load up. However, because of the huge dependency on callbacks, my code is still executing long after the action has returned the HTML.
I must be missing something silly (or not quite getting the whole async thing) but how on earth do i stop my action from finishing until i have all my data ready to render the view?!
Cheers
I'd recommend getting very intimate with the async library
The docs are pretty good with that link above, but it basically boils down to a bunch of very handy calls like:
async.parallel([
function(){ ... },
function(){ ... }
], callback);
async.series([
function(){ ... },
function(){ ... }
]);
Node is inherently async, you need to learn to love it.
It's hard to tell exactly what the problem is but here is a guess. Assuming you have only one external call your code should look like this:
exports.myController = function(req, res) {
longExternalCallOne(someparams, function(result) {
// you must render your view inside the callback
res.render('someview', {data: result});
});
// do not render here as you don't have the result yet.
}
If you have more than two external calls your code will looks like this:
exports.myController = function(req, res) {
longExternalCallOne(someparams, function(result1) {
longExternalCallTwo(someparams, function(result2) {
// you must render your view inside the most inner callback
data = {some combination of result1 and result2};
res.render('someview', {data: data });
});
// do not render here since you don't have result2 yet
});
// do not render here either as you don't have neither result1 nor result2 yet.
}
As you can see, once you have more than one long running async call things start to get tricky. The code above is just for illustration purposes. If your second callback depends on the first one then you need something like it, but if longExternalCallOne and longExternalTwo are independent of each other you should be using a library like async to help parallelize the requests https://github.com/caolan/async
You cannot stop your code. All you can do is check in all callbacks if everything is completed. If yes, go on with your code. If no, wait for the next callback and check again.
You should not stop your code, but rather render your view in your other resources callback, so you wait for your resource to be reached before rendering. That's the common pattern in node.js.
If you have to wait for several callbacks to be called, you can check manually each time one is called if the others have been called too (with simple bool for example), and call your render function if yes. Or you can use async or other cool libraries which will make the task easier. Promises (with the bluebird library) could be an option too.
I am guessing here, since there is no code example, but you might be running into something like this:
// let's say you have a function, you pass it an argument and callback
function myFunction(arg, callback) {
// now you do something asynchronous with the argument
doSomethingAsyncWithArg(arg, function() {
// now you've got your arg formatted or whatever, render result
res.render('someView', {arg: arg});
// now do the callback
callback();
// but you also have stuff here!
doSomethingElse();
});
});
So, after you render, your code keeps running. How to prevent it? return from there.
return callback();
Now your inner function will stop processing after it calls callback.

Stop execution after promise times out

I've been using the Q module to implement promises on a project I'm working on.
I'm using the static method Q.fncall() to create a promise out of a node.js style function (based on callbacks returning err,result).
The problem is that I need to stop the execution of said function after a certain amount of time, so I used the function "timeout" of the Q module. So, after x amount of time, the "error" callback on the done function executes and let's me handle the timeout but the function itself keeps getting executed until it reaches its final callback even if the handler is not listening anymore.
The question is: Is there any way to stop the execution of a function after the timeout is executed? I know I can just set a variable on the timeout handler and keep checking in the function if the timeout is over, but I'm hoping for a cleaner way of achieving this.
The code is as follows:
Q.nfcall(test1, id)
.timeout(1000)
.done(
function (value) {
console.log("SUCCESS: " + value);
},
function (reason) {
console.log("ERROR " + reason);
},
function (progress) {
console.log("PROGRESS " + progress);
}
);
And the test1 function:
function test1(id,callback){
db_rw_pool.query("SELECT * FROM table WHERE id=?",[id], function(err,result) {
if(err){
callback(err,null);
}
else {
setTimeout(function(){
console.log("I DON'T WANT YOU TO BRE PRINTED")
callback(null,result);
},2000);
}
return;
});
}
In my ideal situation, the code inside setTimeout(...,2000) should never be executed. Is this possible?
Thanks in advance.
I think you're concerning yourself over a too low level. Once you've ran test1, there's no way to stop db_rw_pool.query from executing, and its callback from being called (unless you'd take special precautions in this db_rw_pool.query method). The results for the SQL query WILL come back. The question is whether the code will swallow these results at some point, or not. The swallowing in this case happens in the code for Q's timeout method. Just place any code you don't want to be executed in the onFulfilled handler of done.
You write
The problem is that I need to stop the execution of said function after a certain amount of time, so I used the function "timeout" of the Q module.
The timeout method won't stop this function from executing. Rather, it returns a new promise that is instructed to fail if the promise it's bound to (the one which you've made with Q.nfcall) is not fulfilled within the set period (1000 ms in this case).
If you somehow want to stop a callback from executing, you could wrap it inside a function that checks for the time. Something like:
function stopExecutingAfter(timeout, fn) {
var stopifAfter = Date.now() + timeout
return function() {
if(Date.now() > stopIfAfter) return
fn.apply(null, arguments)
}
}
Q mainly concerns itself with promises, so it's obvious that it won't do this for you.
Using this technique, you could make a nfcallWithTimeout function that returns a promise while protecting the passed function (by wrapping it in something like the above) as well. Then you don't have to configure the timeout behavior twice.
Consider using another language because there is no way to do this in Javascript.

Resources