I'm newbie in NodeJs. This is my code for learning asynchronous function.
//--------------------- MAIN ---------------
console.log("Endpoint 1\r\n");
testThread(1000000000,function (result){
console.log(">>>>"+result+"\r\n");
});
console.log("Endpoint 2\r\n");
//------------------------------------------
function testThread(data,callback) {
//take a long time
for(j=0;j<data;j++) {
a = 122342342342424242431*3543652636364;
}
//
callback(a);
}
Run it:
node testthread.js
Always the result is:
Endpoint 1
>>>>4.335387639806787e+32
Endpoint 2
System prints "Endpoint 1", take 2 seconds, it prints ">>>>4.335387639806787e+32" after then it prints "Endpoint 2"
I'm not found the asynchronous here.
It should be:
Endpoint 1
Endpoint 2
>>>>4.335387639806787e+32
Please explain me.
Asynchronous functions are functions that call other functions that are asynchronous. There is not other way to implement asynchronous functions in javascript/node.js. Which at first looks like a chicken and egg problem doesn't it? How can one write an asynchronous function if the requirement is that it must call another asynchronous function in order to be asynchronous?
The answer is that the lowest level asynchronous function must be implemented in C.
Fortunately, javascript/node.js has several built-in asynchronous functions implemented in C that we can use as building blocks in javascript to build our own asynchronous functions. Examples of such functions include the http.request() method, the socket.listen() method and probably the simplest setTimeout() and setInterval().
Here's an example of how one could rewrite your code to achieve asynchronous processing;
function long_task (repeat_number, callback) {
// setTimeout is asynchronous, so keep calling it until we're done
function loop () {
if (repeat_number > 0) {
repeat_number --;
setTimeout(loop,1);
}
else {
callback("I'm done!");
}
}
loop();
}
console.log("calling long task");
long_task(10000,function(x){console.log(x)});
console.log("long task started");
This is a total synchronous code and as node.js is single threaded it wont start a second thread this way.
There are several asynchronous tasks like network requests or database calls, but this one is not.
You would have to spawn a child process to have this asynchronous.
See http://nodejs.org/api/child_process.html for more information
Related
I'm new to coding. Trying to understand why try...catch isn't supposed to work in node.js. I've created an example, but contrary to expectations, try...catch seems to be working. Where am I going wrong in my understanding ? Please help.
function callback(error) { console.log(error); }
function A() {
var errorForCallback;
var y = parseInt("hardnut");
if (!y) {
throw new Error("boycott parsley");
errorForCallback = "boycott parsley for callback";
}
setTimeout(callback(errorForCallback),1000);
}
try {
A();
}
catch (e) {
console.log(e.message);
}
// Output: boycott parsley
// Synchronous behaviour, try...catch works
-----------Example re-framed to reflect my understanding after reading answer below----------
function callback(error) { console.log(error); }
function A() {
var errorForCallback;
setTimeout(function(){
var y = parseInt("hardnut");
if (!y) {
// throw new Error("boycott parsley");
errorForCallback = "boycott parsley for callback";
}
callback(errorForCallback);
}, 1000);
}
try {
A();
}
catch (e) {
console.log(e.message);
}
// Output: boycott parsley for callback
// Asynchronous behaviour
// And if "throw new Error" is uncommented,
// then node.js stops
The try-catch approach is something that works perfectly with synchronous code. Not all the programming that you do in Node.js is asynchronous and so in those pieces of synchronous code that you write you can perfectly use a try-catch approach. Asynchronous code, on the other hand, does not work that way.
For instance, if you had two function executions like this
var x = fooSync();
var y = barSync();
You would expect three things, first that barSync() would be executed only after fooSync() has finished, and you would expect that x would contain whatever value is returned by the execution of fooSync before barSync() is executed. Also you would expect that if fooSync throws an exception, barSync is never executed.
If you would use a try-catch around fooSync() you could guarantee that if fooSync() fails you can catch that exception.
Now, the conditions completely change if you would have a code like this:
var x = fooAsync();
var y = barSync();
Now imagine that when fooAsync() is invoked in this scenario, it is not actually executed. It's just scheduled for execution later on. It is as if node would have a todo list, and at this moment it is too busy running your current module, and when it finds this function invocation, instead of running it, it simply adds it to the end of its todo list.
So, now you cannot guarantee that barSync() will run before fooAsync(), as a matter of fact, it probably won't. Now you don't control the context in which fooAsync() is executed.
So, after scheduling the fooAsync() function, it immediately moves to execution of barSync(). So, what can fooAsync() return? At this point nothing, because it has not run yet. So x above is probably undefined. If you would put try-catch around this piece of code it would be pointless, because the function will not be executed in the context of this code. It will be executed later on, when Node.js checks if there are any pending tasks in its todo list. It will be executed in the context of another routine that is constantly checking this todo list, and this only thread of execution is called an event loop.
If your function fooAsync() gets to fail, it will fail in the context of execution of this thread running the event loop and therefore it would not be caught by your try-catch statement, at that point, that module above may have probably finished execution.
So, that is why in asynchronous programing you cannot either get a return value, neither can you expect to do a try-catch, because you code is evaluated somewhere else, in another context different from the one where you think you invoked it. It is as if you could would have done something like this instead:
scheduleForExecutionLaterWhenYouHaveTime(foo);
var y = barSync();
And that's the reason why asynchronous programming requires other techniques to determine what happened to your code when it finally runs. Typically this is notified through a callback. You define a callback function which is called back with the details of what failed (if anything) or what your function produced and then you can react to that.
A little ticky question, First, I have a plugin:
exports.action = function(){
// Running synchronous code
runMyRequest("path/to/url", function(){
// My code is asynchronous
});
}
Then I call this plugin from a require:
var plugin = require('myplugin')
plugin.action();
// continue stuff
Question: Is there any ways at "continue stuff" to check if "My code is asynchronous" is running or finished ? And so wait for it ?
Note: In my real code plugins must call a callback(). The purpose of this question is to do something if plugin's code forget to call my callback()
I don't believe so but you can use setTimeout to call a function if the plugin doesn't call the callback in a specific period of time. If the callback is called you clear the timeout.
Question: ... And so wait for it ?
I've recently created a simple abstraction named WaitFor to call async functions in sync mode (based on Fibers): https://github.com/luciotato/waitfor
First, "action" should have a callback as parameter, because as it is written in your example, it is an async function (returns immediately) but it doesn't have a callback.
your code with wait.for:
exports.action = function(callback){
// Running synchronous code
runMyRequest("path/to/url", function(){
// My code is asynchronous
...
callback(err,data);
});
}
Then call this plugin from a require:
var wait = require('wait.for')
var plugin = require('myplugin')
...in a fiber...
wait.for(plugin.action); // waits until callback is called (WITHOUT BLOCKING NODE)
// continue stuff
Wait.for will give you other advantages, like sequential try-catch programming, when needed.
I have a code snippet in nodejs like this:
in every 2 sec, foo() will be called.
function foo()
{
while (count < 10)
{
doSometing()
count ++;``
}
}
doSomething()
{
...
}
The limitation is, foo() has no callback.
How to make while loop execute and foo() completes without waiting for dosomething() to complete (call dosomething() and proceed), and dosomething() executes parallely?
I think, what you want is:
function foo()
{
while (count < 10)
{
process.nextTick(doSometing);
count ++;
}
}
process.nextTick will schedule the execution of doSometing on the next tick of the event loop. So, instead of switching immediately to doSometing this code will just schedule the execution and complete foo first.
You may also try setTimeout(doSometing,0) and setImmediate(doSometing). They'll allow I/O calls to occur before doSometing will be executed.
Passing arguments to doSomething
If you want to pass some parameters to doSomething, then it's best to ensure they'll be encapsulated and won't change before doSomething will be executed:
setTimeout(doSometing.bind(null,foo,bar),0);
In this case doSometing will be called with correct arguments even if foo and bar will be changed or deleted. But this won't work in case if foo is an object and you changes one of its properties.
What the alternatives are?
If you want doSomething to be executed in parallel (not just asynchronous, but actually in parallel), then you may be interested in some job-processing solution. I recommend you to look at kickq:
var kickq = require('kickq');
kickq.process('some_job', function (jobItem, data, cb) {
doSomething(data);
cb();
});
// ...
function foo()
{
while (count < 10)
{
kickq.create('some_job', data);
count ++;
}
}
kickq.process will create a separate process for processing your jobs. So, kickq.create will just register the job to be processed.
kickq uses redis to queue jobs and it won't work without it.
Using node.js build-in modules
Another alternative is building your own job-processor using Child Process. The resulting code may look something like this:
var fork = require('child_process').fork,
child = fork(__dirname + '/do-something.js');
// ...
function foo()
{
while (count < 10)
{
child.send(data);
count ++;
}
}
do-something.js here is a separate .js file with doSomething logic:
process.on('message', doSomething);
The actual code may be more complicated.
Things you should be aware of
Node.js is single-threaded, so it executes only one function at a time. It also can't utilize more then one CPU.
Node.js is asynchronous, so it's capable of processing multiple functions at once by switching between them. It's really efficient when dealing with functions with lots of I/O calls, because it's newer blocks. So, when one function waits for the response from DB, another function is executed. But node.js is not a good choice for blocking tasks with heavy CPU utilization.
It's possible to do real parallel calculations in node.js using modules like child_process and cluster. child_process allows you to start a new node.js process. It also creates a communication channel between parent and child processes. Cluster allows you to run a cluster of identical processes. It's really handy when you're dealing with http requests, because cluster can distribute them randomly between workers. So, it's possible to create a cluster of workers processing your data in parallel, though generally node.js is single-threaded.
Is is possible to convert an asynchronous/callback based method in node to blocking/synchronous method?
I'm curious, more from a theoretical POV, than a "I have a problem to solve" POV.
I see how callback methods can be converted to values, via Q and the like, but calling Q.done() doesn't block execution.
The node-sync module can help you do that. But please be careful, this is not node.js way.
To turn asynchronous functions to synchronous in 'multi-threaded environment', we need to set up a loop checking the result, therefore cause blocking.
Here’s the example code in JS:
function somethingSync(args){
var ret; //the result-holding variable
//doing something async here...
somethingAsync(args,function(result){
ret = result;
});
while(ret === undefined){} //wait for the result until it's available,cause the blocking
return ret;
}
OR
synchronize.js also helps.
While I would not recommend it, this can easy be done using some sort of busy wait. For instance:
var flag = false;
asyncFunction( function () { //This is a callback
flag = true;
})
while (!flag) {}
The while loop will continuously loop until the callback has executed, thus blocking execution.
As you can imagine this would make your code very messy, so if you are going to do this (which I wouldn't recommend) you should make some sort of helper function to wrap your async function; similar to Underscore.js's Function functions, such as throttle. You can see exactly how these work by looking at the annotated source.
I have always wondered about this and have never found a convincing answer.
Please consider the following case:
var toAddress = '';
if(j==1)
{
toAddress="abc#mydomain.com";
}
else
{
toAddress="xyz#mydomain.com";
}
sendAlertEmail(toAddress);
Can I be certain that by the time my sendAlertEmail() function is called, I will have 'toAddress' populated?
For code like the sample you provided:
var toAddress = '';
if(j==1)
{
toAddress="abc#mydomain.com";
}
else
{
toAddress="xyz#mydomain.com";
}
sendAlertEmail(toAddress);
You can definitely be certain that it is strictly sequential. That is to say that the value of toAddress is either "abc#mydomain.com" or "xyz#mydomain.com".
But, for code like the following:
var toAddress = '';
doSomething(function(){
if(j==1)
{
toAddress="abc#mydomain.com";
}
else
{
toAddress="xyz#mydomain.com";
}
});
sendAlertEmail(toAddress);
Then it depends on whether the function doSomething is asynchronous or not. The best place to find out is the documentation. The second best is looking at the implementation.
If doSomething is not asynchronous then the code execution is basically sequential and you can definitely be certain that toAddress is properly populated.
However, if doSomething is asynchronous then you can generally be certain that the code execution is NOT sequential. Since that is one of the basic behavior of asynchronous functions - that they return immediately and execute the functions passed to them at a later time.
Not all functions that operate on functions are asynchronous. An example of synchronous function is the forEach method of arrays. But all asynchronous functions accept functions as arguments. That's because it's the only way to have some piece of code executed at the end of the asynchronous operation. So whenever you see functions taking functions as arguments you should check if it's asynchronous or not.
Node.js is single threaded (or at least the JS execution is) so since all the above code is synchronous and lined up to all occur during the same tick it will run in order and thus toAddress must be populated.
Things get complicated once you introduce an asynchronous function. In the asynchronous case it it possible for variable to shift between lines, since ticks occur between them.
To clarify during each tick the code is simply evaluated from the top of the execution to the bottom. During the first tick the scope of execution is the whole file, but after that it's callbacks and handlers.
The code that you wrote was pretty simple to point out the asynchronous behavior. Take a look at this code :
var toAddress = 'abc#mydomain.com';
if(j==1)
{ func1(toAddress); }
else
{ func2(toAddress); }
sendAlertEmail(toAddress);
There is no guarantee that sendAlertEmail will execute only after func1 or func2 (the if else conditional) has been executed. In node functions return immediately when they are called and execute the next function called. If you want to make sure they execute sequentially use callbacks or use a library like async.