An if statement will execute synchronous before a callback? - node.js

I have to change the value of an json element, if it exists, before making an async function call, but I'm not sure if this code will execute in the order that I want. Here is a simple example:
function first_function(json, callback) {
get_only_valid_elements_json(json, function(valid_json) {
if (valid_json.element) {
valid_json.element = something;
}
update_something(valid_json, function(error) {
if (error) {
return callback(error);
} else {
return callback({success:"YAY"});
}
});
});
}
I would like to know how the following code will execute and more important why. Thanks!

It looks right to me.
Assuming get_only_valid_elements_json, and update_something call the function passed to them when they're finished with their job, this is how it is executed:
it calls get_only_valid_elements_json, and first_function function returns
when get_only_valid_elements_json finishes (i.e. when it calls the callback function passed in the second argument), it will execute the if statement, and conditionally, its block
then, update_something is called and then function(valid_json) {...} returns
when update_something finishes (i.e. calls the callback function), it will execute the if (error) statement and the appropriate block
the callback function is called (either with error or success), signalling that get_only_valid_elements_json finished its job
So the functions synchronously return before their "real job" is done.
The reason for asynchronous calls is to not block the executing process when you're waiting for something, e.g. a response to an AJAX call. You just tell the browser to execute a given function when the response is received, so when it receives the response it calls the function you gave to the AJAX call, which calls the function given to update_something, which then calls the callback given to first_function.

Related

node js callback - Will the order always be the same?

I wrote the following function that takes a callback. I always thought that the content of a callback might be executed later. In this case it doesn't...
doesSomething(function(){
console.log("1");
var i = 0;
while (i < 10000)
{
console.log("hello");
i = i + 1;
}
});
console.log("2");
console.log("3");
Whatever I do, "2" and "3" always comes after "1" and a thousand of "hello".
Like this:
1
hello
hello
...
hello
hello
2
3
What I thought it would do:
2
3
1
hello
hello
...
hello
hello
Even if this behaviour makes my life simpler I don't really understand why the execution is procedural.
Do you think that in some case it might go reverse ?
It all depends upon how doSomething() calls its callback. If it calls the callback synchronously (e.g. before it returns), then everything in that function will execute before doSomething() returns. If it calls it asynchronously (sometime after it returns), then you will get a different order.
So, the order is determined by the code that you do not show us in doSomething().
Based on the order you observe, doSomething() must be calling its callback synchronously and thus it will execute in order just like any other synchronous function call.
For example, here are two scenarios:
function doSomething(callback) {
callback();
}
This calls the callback passed to it synchronously and thus it will execute before doSomething() returns and thus it will execute before code that follows.
Whereas something like this;
function doSomething(callback) {
fs.writeFile('foo.txt', callback);
}
or:
function doSomething(callback) {
setTimeout(callback, 50);
}
Will execute the callback asynchronously sometime later after the function has already returned and you will see a different execution order with your console.log() statements.
From the output that you mention, I can say that there is nothing asynchronous happening in your code inside doesSomething and is probably looking like this:
function doesSomething(callback) {
<maybe some synchronous operations, e.g. no ajax or filesystem calls>
callback();
}
, so the order of the calling functions will be always the same, like you posted above:
doesSomething(callback)
console.log(2)
console.log(3)
If you want the order you mention you should call them like this:
console.log(2)
console.log(3)
doesSomething(callback)
This does not have to do something with node.js in particular. It is the way methods are executed in JavaScript, which is synchronous since it is single threaded.
When you call the method doesSomething(callback) it immediately executes it and nothing else until it completes
javascript is a single threaded language, but not the node.js runtime or the browser. There are certain functions provided by node.js or the browser that would trigger for a function to be assigned to a task queue to be processed in a separate thread
lets take your example and make dosomething async
this is your synchronous code that would print, 1 hello...,2,3
function doesSomething(callback) {
callback();
}
doesSomething(function(){
console.log("1");
var i = 0;
while (i < 3)
{
console.log("hello");
i = i + 1;
}
});
console.log("2");
console.log("3");
and this is the async code, that prints out 3, 2, 1, hello ...
function doesSomething(callback) {
setTimeout(callback, 0);
}
doesSomething(function(){
console.log("1");
var i = 0;
while (i < 3)
{
console.log("hello");
i = i + 1;
}
});
console.log("2");
console.log("3");
to explain why the second code is async, you have to understand that setTimeout is not part of javascript, its an api provided by node.js and the browsers. setTimeout puts the callback function into a queue to be processed. At this time a separate thread runs the setTimeout and when the timer ends it puts the callback into a callback queue, and when the call stack is clear, whatever is in the callback queue will be moved to the call stack and processed.
in node you can use process.nextTick(yourFunction); to make it async, this is just another function that nodejs provides you which is better than using setTimeout (which I wont get into here) you can checkout https://howtonode.org/understanding-process-next-tick to understand more about process.nextTick
for more info check out this video https://youtu.be/8aGhZQkoFbQ?t=19m25s

Async.until function parameters

async.parallel([
function(callback) { //This is the first task, and callback is its callback task
db.save('xxx', 'a', function(err) {
//Now we have saved to the DB, so let's tell async that this task is done
callback();
});
},
function(callback) { //This is the second task, and callback is its callback task
db.save('xxx', 'b', callback); //Since we don't do anything interesting in db.save()'s callback, we might as well just pass in the task callback
}
], function(err) { //This is the final callback
console.log('Both a and b are saved now');
});
Hey I found this code online when I trying to understand async in node.js and my question I have with the code above is in the array of functions in async.parallel, what is the callback parameter that is passed in each function? Where does that callback parameter come from and what is the purpose of that variable? I am sorry if this is a dumb question, but I can't grasp a solid understanding of this callback's...
The contract that async.parallel() defines is that you pass it an array of functions. It will then call each of those functions and pass those function a single argument that is a function reference (I think of it as a completion callback). For async.parallel() to work properly, your function that you pass in the array has to call that function reference when your async operation is done. When it calls that function reference, it can pass an error argument and a result argument. If the error argument is truthy, then it will stop further processing and feed that error back to the calling code.
The function that async passes a reference to is internal to the async library and when you call it, the async library does some housekeeping to keep track of how many asynchronous operations are still going, whether they're all done now, whether further processing should stop due to error, etc...
You can essentially think of it like the async library completion function. When your asynchronous operation is done, you have to call that completion function so that the async library knows that your operation is now done. That's how it is able to manage and keep track of your multiple async operations. If you don't call that completion callback, then the async library never knows when your asynchronous operation is done.
The callback parameter is a function created by async. When you call it in each of the array functions, it signals async that the function completed. In that way, you can control when your function is done - when you call callback.
When callback is called from all the array functions, the final function is called.

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 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