Introduction to non-blocking methods in NodeJs

Source: Internet
Author: User
Tags sleep function

First, we use NodeJs to build a basic server.
Index. js Copy codeThe Code is as follows: var requestHandler = require ("./requestHandler ");
Var server = require ("./server ");
Var route = {
"/Hello": requestHandler. hello,
"/Upload": requestHandler. upload
};
Server. start (route );

Server. jsCopy codeThe Code is as follows:

Server. jsCopy codeThe Code is as follows: var http = require ("http ");
Var url = require ("url ");
Exports. start = function (route ){
Var server = http. createServer (function (req, res ){
Var pathName = url. parse (req. url). pathname;
Var handler = route [pathName];
If (handler ){
Console. log ("Through path:" + pathName + ":" + new Date (). getTime ());
Handler (res );
} Else {
Res. writehead( 404, {"Content-Type": "text/plain "});
Res. end ();
}
});
Server. listen (8088 );
};

RequestHandler. jsCopy codeThe Code is as follows: exports. hello = function (res ){
Res. writehead( 200, {"Content-Type": "text/plain "});
Res. write ("say hello .");
Res. end ();
};
Exports. upload = function (res ){
Res. writehead( 200, {"Content-Type": "text/plain "});
Res. write ("upload ");
Res. end ();
};

In cmd, type node index. js to start.
However, the above Code is blocked. If the createServer callback function takes a long time. This will block node. js event polling.
In NodeJS, the key to its efficiency lies in the rapid return of event loops.
The transformation of requestHandler. js is as follows. In this example, the callback of createServer cannot be returned in time because the event loop is blocked by the sleep function.Copy codeThe Code is as follows: function sleep (milliSecond ){
Var startTime = new Date (). getTime ();
Console. log (startTime );
While (new Date (). getTime () <= milliSecond + startTime ){
}
Console. log (new Date (). getTime ());
}
Exports. hello = function (res ){
Sleep (20000 );
Res. writehead( 200, {"Content-Type": "text/plain "});
Res. write ("say hello .");
Res. end ();
};
Exports. upload = function (res ){
Res. writehead( 200, {"Content-Type": "text/plain "});
Res. write ("upload ");
Res. end ();
};

Then, press http: // localhost: 8088/hello, and then type http: // localhost: 8088/upload. You will find that, although upload does not need to spend too much time, it will have to wait until the completion of hello.
We try to find the asynchronous call method. For example, the upload in formidable is not blocked by tests. View the formidable source code and find the following code:Copy codeThe Code is as follows: IncomingForm. prototype. parse = function (req, cb ){
This. pause = function (){
Try {
Req. pause ();
} Catch (err ){
// The stream was destroyed
If (! This. ended ){
// Before it was completed, crash & burn
This. _ error (err );
}
Return false;
}
Return true;
};
This. resume = function (){
Try {
Req. resume ();
} Catch (err ){
// The stream was destroyed
If (! This. ended ){
// Before it was completed, crash & burn
This. _ error (err );
}
Return false;
}
Return true;
};
This. writeHeaders (req. headers );
Var self = this;
Req
. On ('error', function (err ){
Self. _ error (err );
})
. On ('aborted', function (){
Self. emit ('aborted ');
})
. On ('data', function (buffer ){
Self. write (buffer );
})
. On ('end', function (){
If (self. error ){
Return;
}
Var err = self. _ parser. end ();
If (err ){
Self. _ error (err );
}
});
If (cb ){
Var fields ={}, files = {};
This
. On ('field', function (name, value ){
Fields [name] = value;
})
. On ('file', function (name, file ){
Files [name] = file;
})
. On ('error', function (err ){
Cb (err, fields, files );
})
. On ('end', function (){
Cb (null, fields, files );
});
}
Return this;
};

In parse, it is blocked to parse the head information. However, the real upload file is in req. on (data). It uses event-driven, non-blocking. That is to say, his non-blocking model relies on the entire nodeJS event dispatch architecture.
So what should I do when I consume a lot of computing like sleep, but cannot rely on nodeJS to dispatch the architecture?
Now we will introduce a method similar to html5 WebWorker.
Transform requestHandler. js as follows:Copy codeThe Code is as follows: var childProcess = require ("child_process ");
Exports. hello = function (res ){
Var n = childProcess. fork (_ dirname + "/subProcess. js ");
N. on ('message', function (){
Res. writehead( 200, {"Content-Type": "text/plain "});
Res. write ("say hello .");
Res. end ();
});
N. send ({});
};
Exports. upload = function (res ){
Res. writehead( 200, {"Content-Type": "text/plain "});
Res. write ("upload ");
Res. end ();
};

Add subProcess. jsCopy codeThe Code is as follows: function sleep (milliSecond ){
Var startTime = new Date (). getTime ();
Console. log (startTime );
While (new Date (). getTime () <= milliSecond + startTime ){
}
Console. log (new Date (). getTime ());
}
Process. on ('message', function (){
Sleep (20000 );
Process. send ({});
});

Test. When hello is still waiting, upload has returned.
Conclusion:
Recently, I have read many NodeJs articles in the blog Park. Everyone thinks NodeJS is asynchronous. However, to what extent is asynchronous, this concept is not mentioned in many articles.
Actually, NodeJS is a double-layer architecture. C ++, and javascript. It is also single-threaded. This is especially important. Node actually uses C ++ to call js commands using v8, and maintains an Event sequence in order to realize the call sequence. Therefore, within a js function, its call will definitely block other functions. Therefore, process. nextTick and setTimeout mentioned on the Internet cannot generate new threads to ensure that they are not blocked. The implementation is just an issue of the element sequence of the Event sequence. Compared with setTimeout, the implementation of process. nextTick is much simpler. It is directly added to the top layer of the Event Sequence (what is an Event ). SetTimeout adds a c ++ thread and adds callback to the Event sequence at the specified time.
Take the file io of Node as an example. The second parameter is a callback. The first thing in node is to record the callback, call the underlying c ++, and call the c ++ process. You can think of it as Asynchronous. Because it has already reached c ++, rather than js. Therefore, exec is asynchronous until callback is triggered. http. createServer is asynchronous until callback is triggered. There are many other methods, such as calling methods of mysql. I don't know if you have read the source code. I believe this process is very fast. Then, the Node is hidden in c ++ during the callback process. It is also asynchronous.
What I want to explain in this article is what to do if the js end has a lot of time-consuming operations. Use the method described above to open the c ++ thread with js. This subprocess. js is not maintained internally in the node event sequence. Is a new thread, so it does not block other js Functions

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.