node.js setImmediate unexpected behavior - node.js

As I understand, the differences between process.nextTick() and setImmediate() are the followings:
callbacks scheduled by process.nextTick() will ALL be executed before entering the next event loop, while callbacks scheduled by setImmediate() will only be executed ONE per event loop.
Base on the characteristics stated above, it can be said that: recursive call of process.nextTick() can cause the program to hang up, while recursive call of setImmediate() will not.
Then I've written some testing code to verify the statements above, here is my code:
process.nextTick(function() {
console.log('nextTick1');
});
process.nextTick(function() {
console.log('nextTick2');
});
setImmediate(function() {
console.log('setImmediate1');
process.nextTick(function() {
console.log('nextTick3');
});
});
setImmediate(function() {
console.log('setImmediate2');
});
My expected result should be
nextTick1, nextTick2, setImmediate1, nextTick3, setImmediate2
, but what I actually got is
nextTick1, nextTick2, setImmediate1, setImmedate2, nextTick3
Then I've run another test to study the behavior of setImmediate():
//the following code is using express as the framework
app.get('/test', function (req, res) {
res.end('The server is responding.');
});
app.get('/nexttick', function (req, res) {
function callback() {
process.nextTick(callback);
}
callback();
res.end('nextTick');
});
app.get('/setimmediate', function (req, res) {
function callback() {
setImmediate(callback);
}
callback();
res.end('setImmediate');
});
Step1: I accessed http://localhost:3000/nexttick on my browser and I got the text nexttick.
Step2: I accessed http://localhost:3000/test to test if my server is still responding to requests, and I didn't get any response, the browser kept waiting for response. This is nothing surprising because the recursive call of process.nextTick() had hanged up the server.
Step3: I restarted my server.
Step4: I accessed http://localhost:3000/setimmediate and got the text setimmediate
Step5: I accessed http://localhost:3000/test again to test if my server is still responding. And the result is as the same as Step2, I didn't get any response and the browser kept waiting for response.
This means the behavior of process.nextTick() and setImmediate() is pretty much the same but as I know they are not.
I was wondering why is this happening or have I misunderstood sth. Thank you.
P.S. I am running Node v0.12.7 under Windows 10.

Actually your test results looks ok (I only refer to the first test).
Your comments "setImmediate() will only be executed ONE per event loop." is wrong, See https://nodejs.org/api/timers.html#timers_setimmediate_callback_arg
and thats the reason you don't understand the first test results.
Basically process.nextTick will put your function at the end of the current event loop while setImmediate will put it at the next event loop.
But executing multiple setImmediate is ok and they will all go to that same next event loop.
In
setImmediate(function() {
console.log('setImmediate1');
process.nextTick(function() {
console.log('nextTick3');
});
});
setImmediate(function() {
console.log('setImmediate2');
});
Basically you have put 2 function sthat will be invoked in next event loop, and in one of them you put another nextTick which will be invoked at the end of that same cycle but at the end of that same cycle.
So it will first invoke those 2 setImmediate and than the nextTick that was called in the first.

Related

Request callback does not get called until end

Why is Request callback not called at all in this example?
Output of this would be:
here
now here
"did it!" or any log commands in callback does not get called.
var request = require('request');
d=0;
console.log("here");
request('http://www.google.com', function (error, response, body) {
console.log('error:', error); // Print the error if one occurred
console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
console.log('body:', body); // Print the HTML for the Google homepage.
d=1;
});
console.log("now here");
while(d==0){}
console.log("did it!");
If I remove "while(d==0){}". Then it gets called.
you actually stuck in while(d==0){} because you are making async code with sync
The async code fires in the event loop so the flow of the application going with the sync code which will fire the while loop and start iterate.
Your process is stuck in an endless loop.
Replace your d=1 in the callback with console.log("did it!"), and get rid of the while loop.
(ie. everything you want to run after the response is returned, you should put inside the callback function)
The problem is your while is starving the main thread, the callback passed to request will never be executed since the main flow will never finish execute, I'd suggest you to study a little bit of the event loop of node.js.
This while loop starves the event loop by running
infinitely, greedily checking and rechecking a value that is never given a chance
to change, as the event loop is never given a chance to schedule your request callback
for execution.

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.

Does async.parallel also parallelise blocking code?

I'm trying to understand the behaviour of the async package in relation to parallelisation of code. From what I understand, it is helpful to structure code in order to avoid callback hell/soup, but is that the only advantage?
async.parallel([
function(next) {
apiCallTo3rdParty(next);
},
function(next) {
apiCallTo3rdParty(next);
},
function(next) {
apiCallTo3rdParty(next);
}
], function(err, res) {
// do something else with returned data
});
In the code above, all three api calls would be made without waiting for the other to complete. As per spec. The final callback would be called after the longest API call returns, as the rest would have completed prior.
However, if I changed the code so that it made a couple blocking operations, what would happen?:
async.parallel([
function(next) {
sleep(5);
},
function(next) {
sleep(5);
},
function(next) {
sleep(5);
}
], function(err, res) {
// do something else with returned data
});
Taking "Node.js is Single Threaded" at face value, we'd take it to mean that the async block would execute its final callback after fifteen seconds, but knowing that "Node.js maintains its own internal thread pool", can we assume that Node would run each callback in its own thread, truly parallelise the functions, and call the final callback after 5 seconds?
Short answer: your code would take 15 seconds to execute. Why?
There's no way to run parallel code in javascript. The only way to run synchronous code without blocking the event loop would be to spawn a Worker. Since the async module doesn't care about workers, it would have to wait for your functions to be done before it can call the next one.
Consider the following:
sleep(5)
sleep(5);
sleep(5);
Obviously it would take 15 seconds. Now even if you make this "parallel" the way async does:
function parallel () {
process.nextTick(function(){
sleep(5);
});
process.nextTick(function(){
sleep(5);
});
}
parallel();
console.log("this is called immediately");
process.nextTick(function(){
console.log("this is called 10 secs later");
});
The code is executed immediately, but as soon as the event loop yields to those queued up methods, they are gonna block other code from executing.

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

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.

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