Event-driven asynchronous callbacks of Nodejs - javascript

I am reading The Node Beginner Book. In the chapter Event-driven asynchronous callbacks, the author gives an example to illustrate the idea of asynchronous callbacks. The code example is like:
var result = database.query("SELECT * FROM hugetable");
console.log("Hello World");
After adding a callback function to database.query, the code becomes asynchronous:
database.query("SELECT * FROM hugetable", function(rows) {
var result = rows;
});
console.log("Hello World");
My question is why the database.query() function becomes asynchronous simply after adding a callback function.
I have no experience with Javascript and JQuery before, that might be the reason I cannot understand.

There are many functions in node.js that have both an asynchronous flavor and a synchronous flavor. For example, there are two ways to read the contents of a file (docs):
//asynchronous
fs.readFile("filename.txt", function(err, data) {
});
//synchronous
var data = fs.readFileSync("filename.txt");
The example the author provides does in fact look somewhat confusing, but its possible that the database.query makes an asynchronous call depending on whether a callback is passed in as the second argument.
For example, it could be implemented something like this:
function query(queryString, callback) {
if(callback !== undefined) {
queryInternal(queryString, callback);
return;
}
else {
return queryInternalSync(queryString);
}
}
In general, I think the convention is that a function is either asynchronous or synchronous (not both) so your intuition is right.
Note that in the synchronous case, console.log will be executed after result has the queried contents whereas in the asynchronous case, console.log will be executed as soon as query function returns and before callback is executed.

Asynchronously means it don't waits for the response and go to the next statements
to be executed
In your second example the callback function handles your response while executing this,
it doesn't waits and console.log("Hello World"); shows the output in console.
Read this:
http://blog.mixu.net/2011/02/01/understanding-the-node-js-event-loop/
http://nodemanual.org/latest/nodejs_dev_guide/writing_asynchronous_code.html
http://www.sebastianseilund.com/nodejs-async-in-practice

Related

Isn't it better to be async with Node

Here is my code
var x = 0
data.results[0].taxonomies.some(function(e){
if(taxo.indexOf(e.code)!=-1){ //if at least one code from the data base is in my list of codes
callback(validLic(data.results[0].taxonomies)) //return true after some other validations
return true
}else{
x++
return false
}
})
if(x==data.results[0].taxonomies.length){callback(false)}//if the entire array was processed, and I didn't find anything I was looking for, return false
I'd like someone to confirm that due the async nature of node, the last if statement is at some point, bound to fire off before I'm done processing the array.
How can I better manage this situation without the help of some sync or parallel library?
The reason I ask it that way is because I'm under the impression that if I can't write something to be completely async, then I'm not writing it efficiently, right?
EDIT:
Based on Luc Hendirks' logic, I have changed my code to this:
var flag = data.results[0].taxonomies.some(function(e){
if(taxo.indexOf(e.code)!=-1){ //if at least one code from the data base is in my list of codes
return true
}else{
return false
}
})
if(flag==true){
callback(validLic(data.results[0].taxonomies))
}else{
callback(false)
}
Because this follows the sync traits outlined below, I shouldn't have an issue with flag being undefined before the callback is called now right?
Javascript (and Node) are single threaded, meaning it has only 1 CPU available. If the functions you call only require CPU time, making it async is useless. If you need to call a function and the CPU has to wait (do nothing), then making it async is very useful. Because while it is waiting until the function is finished it can do something else.
A function that checks if a url is valid with a regular expression can be synchronous, as the CPU needs to do some calculations and you get the result. If the function actually does a GET request and checks the response code, the CPU has to wait until the response is received. In the meantime it could do something else, so this function should be made asynchronous.
The difference of a synchronous and asynchronous function is that a synchronous function returns a value:
function(a) { return a; }
and an asynchronous function returns the result using a callback function (this is an actual function that you put in as a function argument):
function(callback){
// Do something that takes time but not CPU, like an API call...
callback('Some result');
}
A synchronous function is called like this:
var a = something();
Asynchronous like this:
something(function(result){
console.log(result);
});
So to answer your question, if some() is an asynchronous function, then the last if statement can be executed before the some function is finished. Because: the CPU does not want to wait. It can do other stuff while waiting. That's the power of asynchronous programming. t
It is also important to know that "parallel" does not exist in Javascript/Node. There is only 'doing stuff instead of waiting', like executing multiple API calls at the same time. That is not parallel computing as in using multiple threads.
Here is some more info: What is the difference between synchronous and asynchronous programming (in node.js)

Synchronous vs Asynchronous Nodejs

I was automating a webpage using the Mocha testing framework, and came upon the terms Synchronous and Asynchronous code.
I'm familiar with synchronous and asynchronous events when you send an HTTP request...but I've never heard of code being synchronous and asynchronous.
Anyone care to explain...I saw on previous questions that it has something to do with a callback, but even then I'm still pretty confused about the concept.
Below is a simplified version of my server code. I demonstrate both synchronous code (after you start doing an operation, no further operations are begun until it finishes) and asynchronous code (you start doing an operation, then continue to do other operations, and at some later point you "callback" or get a result from the first operation.)
This has some important consequences. Nearly every time you call an async function:
the return value from your async function is useless, because the function will return immediately, although finding the result takes a long time.
you have to wait until the callback function is executed to have access to the result.
lines of code following the call to the asynchronous function will execute BEFORE the asynchronous callback function runs.
As an example, the order of the console.logs in my code below will be:
line 3 - before sync
line 8 - after sync, before async
line 16 - after async call, outside callback
line 14 - inside async call and callback
// synchronous operations execute immediately, subsequent code
// doesn't execute until the synchronous operation completes.
console.log('line 3 - before sync');
var app = require('express')();
var cfgFile = require('fs').readFileSync('./config.json');
var cfg = JSON.parse(cfgFile);
var server = require('http').createServer(app);
console.log('line 8 - after sync, before async');
// When you call an asynchronous function, something starts happening,
// and the callback function will be run later:
server.listen(cfg.port, function(){
// Do things that need the http server to be started
console.log('line 14 - inside async call and callback');
});
console.log('line 16 - after async call, outside callback');
Synchronous code will strictly be processed line by line whereas asynchronous code will continue to the next line while previous lines of code are still being processed.
For asynchronous code, in the following snippet, you would expect World to be logged to console before Hello because the database query requires more of the computer's resources and therefore takes more time. console.log('World') would finish executing before the query.
var Person = mongoose.model('Person', personSchema);
Person.findOne({ 'name.last': 'Ghost' }, function(err, person) {
if(err)
throw err;
else
console.log('Hello');
});
console.log('World');
In synchronous code, Hello will be logged before World because the query finishes executing before any following lines are executed.
Synchronous Code basically means the lines of code are executed in the order they are written. Synchronous events will immediately execute an associated callback like it would a direct function call so the end result is the same.
In general, Asynchronous Code is executed separately and concurrently from the calling code. e.g. Calling setTimeout will immediately return and execute the next expression but it will have started an action that at some point in the future it will fire an Asynchronous Event that calls the specified callback.
The Mocha test framework supports both types of code and it supplies the done() callback for asynchronous code. done() is the callback that lets Mocha know when the test complete.
Asynchronous test code, From http://mochajs.org/
describe('User', function() {
describe('#save()', function() {
it('should save without error', function(done) { // done is a callback
var user = new User('Luna');
user.save(function(err) { // save is async db call that starts here, completes whenever
if (err) throw err;
done();
});
});
});
});
Testing synchronous code doesn't require done(), the test code is expected to executed in order. So when the last expression is executed, the test is over.

Callback function in node.js

I am new to node.js and relatively new to javascript. I have understood how callbacks works and wanted to try out a function myself. Here is my code:
MyScript.js:
var calledfunction = function()
{
console.log("This is a called function");
for(i=0;i<1090660;i++)
{
console.log(i);
}
console.log('done');
};
var sayHello = require('./sayhello.js');
objhello = new sayHello();
objhello.setupSuite(1,calledfunction);
console.log('Next statement;');
sayhello.js
var _ = require('underscore');
module.exports = exports = CLITEST;
function CLITEST(param1,param2)
{
}
_.extend(CLITEST.prototype, {
setupSuite: function (here,callback) {
console.log(here);
console.log('This is a callback function');
callback();
}
})
The above program is run by executing > node Myscript.js
My question is : the for loop consumes 50 secs to execute and print all the numbers in the console and then only executes the line "Next statement" which is outside the callback function .
Why is this happening? because I read theories saying that the immediate statements will be executed without having to wait for the function to get executed.
The ideal output should have been : print " Next statement" and then print the contents of the for loop
but in the above case it is vice versa ?
This is not a real callback, but rather a simple function call. Function calls are obviously synchronous, as the following statements may rely on their return values.
In order to may the callback async you can use: setTimeout or setImmediate, depending on the actual use case.
See also: Are all Node.js callback functions asynchronous?
As pointed out by one of the commenters, your code is executed in a synchronous fashion. The function calls are executed one after the other, thus no magic is happening and the console.log('Next statement;'); call is executed after the execution of the callback. If you were in a situation in which you had to call a function which executed an asynchronous call (i.e., an AJAX call with a callback) then yes, you would expect the subsequent console.log to be executed right after the asynchronous call.
In other words, in your case the code represents a simple function call, while an asynchronous call would offload the computation of the callback somewhere else, thus the execution of the code where the callback function was called keeps going by printing the statement and won't wait for the execution of the callback.

Mechanics behind Javascript callbacks being asynchronous

I'm having a bit of trouble understanding the mechanics of JS callbacks. I have a fair idea of how callbacks can be used in JS, but I do not understand how a callback is asynchronous.
For e.g., if my understanding is correct, a callback is of the nature:
db.query(param1, param2 , callback_fn1(){..} );
And the implementation of db.query() is along the lines of :
db.prototype.query = function(p1 , p2 , callback ){
//some code
callback();
}
How does the above implementation make db.query an asynchronous function? Does this not mean that a function called callback is passed to query and that function is called inside query? It looks like query is just another synchronous function. Could someone help me understand what I'm overlooking here? Thanks!
The code sample you've shown is actually still synchronous because is instructed to run immediately. An asynchronous callback is a callback that doesn't immediately need to be executed, so it doesn't block the event loop until you instruct it to run.
The most common way in Node.js to do this is with process.nextTick() which runs a specified function when the event loop call stack is empty. Here's an example:
var async = function(args, callback) {
// do some work
process.nextTick(function() {
callback(val);
});
};
Then we call the function like this:
async(args, function(val) {
console.log(val);
});
console.log('end');
In this example, the function async() and console.log('end') are added to the call stack. The call stack empties once both of those functions are run, and once it's empty, console.log(val) then runs.
If you're still confused, think of process.nextTick() as an optimized version of this code:
var fn = function() {};
setTimeout(fn, 0);
It basically means "run this function as soon as possible when you are not busy".
Edit: I just now realized the question is tagged with node.js. My answer is more about Javascript in the browser, #hexacyanide's answer is more about node.js. I guess knowing both doesn't hurt, though!
The way you posted it the code will indeed be blocking. For asynchronous behavior there are a few things you can utilize, such as
setTimeout and setInterval
Built-in, asynchronous methods such as from the FileReader API
Ajax requests
Web workers (see #html5rocks)
Your example code could be written as follows (fiddle):
function doStuff(callback) {
setTimeout(function () {
for (var i = 0; i < 1000; i++) {
// do some busy work
var x = Math.sqrt(i);
}
callback();
}, 0);
}
console.log('start');
doStuff(function () {
console.log('callback called');
});
console.log('after doStuff()');
The setTimeout call will allow the Javascript interpreter/compiler (however exactly they work these days) to run the function in a non-blocking matter which is why (most likely), you will see the output
start
after doStuff()
callback called
Note that asynchronousity is different from multi-threading. Javascript is still single-threaded (with the exception of web workers!).
A more in-depth explanation can be found for example here

Are All Node "callback" Functions Potentially Asynchronous?

I'm a (relative) node newbie getting in the system, and all the enthusiasm in the community for "just write callbacks, everything's asynchronous and event driven, don't worry!" has left me a little confused as to the control flow within a single program (or in more node-ish terms, the control flow during the handling of a single request in a larger program)
If I have the following program running under node
var foo = function(){
console.log("Called Foo");
};
var bar = function(){
console.log("Called Bar");
};
var doTheThing = function(arg1, callback){
callback();
};
doTheThing(true, function() {
foo();
});
bar();
Is there any chance that foo will execute after bar? When I run the program via the command line locally, it's always
Called Foo
Called Bar
but I see so many warnings from well intended evangelists along the lines of don't assume your callback will be called when you think it will, that I'm unclear if they're just warning me about library implementation details, or if node.js does something weird/special when you use a function object as parameter.
No, there's no chance. Not for that code.
If you're writing your own functions, or if you have access to the code, you don't need to assume, you know whether everything's synchronous or otherwise, but if you don't have access to the code, or haven't yet read it, then no, you can't assume callbacks are going to be synchronous.
It's however bad practice to make assumptions like that for two reasons, first is that just because it's synchronous now doesn't mean somebody else, or forgetful future you can't change it later, and secondly, because if it's all synchronous, why are you/they using callbacks in the first place? The entire point of callbacks is to allow for the possibility of asynchronous calls. Using callbacks and then acting like they're always going to be synchronous, even if you know that's the case, makes your code confusing for anybody else coming in.
No
Your sample code is 100% synchronous, single-threaded, simple top-to-bottom. But that's because you don't do any I/O, don't have any real asynchronous calls, and don't use process.nextTick, setTimeout, or setInterval. To more realistically simulate async calls do something like:
function fakeAsync(name, callback) {
setTimeout(function () {
callback(null, name);
}, Math.random() * 5000);
}
function logIt(error, result) {
console.log(result);
}
fakeAsync('one', logIt);
fakeAsync('two', logIt);
fakeAsync('three', logIt);
Run that a few times and you'll see out-of-order results sometimes.
Is there any chance that foo will execute after bar?
In your current code, no. Although your doTheThing function has an asynchronous function signature (i.e. it takes a callback as the last argument, which to an outsider with no knowledge about the function's implementation would suggest that it's asynchronous), it's actually fully synchronous, and callback will be called without yielding to the runtime.
However
You really have no reason to give your doTheThing code an asynchronous signature, unless you're accommodating for introducing real async behavior into doTheThing at some point. And at that point, you have a problem, because the order in which foo and bar are called will flip.
In my opinion, there are only two good ways of writing code like you do: Either make it set in stone that doTheThing will be synchronous (most importantly: that it won't be dependent on I/O), which means that you can simply return from the function:
doTheThing = function(arg1){
return null
};
doTheThing()
foo()
bar()
or change the stub implementation of doTheThing directly to include a call to setImmediate, i.e.
var doTheThing = function(arg1, callback){
setImmediate(function() { callback(); );
};
Note that this can also be written as
var doTheThing = function(arg1, callback){
setImmediate(callback);
};
but that's just because at this moment, callback does not take any arguments. The first version is more close to what you had.
As soon as you do this, bar will always be called before foo, and it has now become safe to introduce async functionality into doTheThing.

Categories

Resources