First we use Nodejs to build a basic server first.
Index.js
Copy Code code as follows:
var RequestHandler = require ("./requesthandler");
var server = require ("./server");
var route = {
"/hello": Requesthandler.hello,
"/upload": requesthandler.upload
};
Server.start (route);
Server.js
Copy Code code as follows:
Server.js
Copy Code code 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.js
Copy Code code as follows:
Exports.hello = function (res) {
Res.writehead ({"Content-type": "Text/plain"});
Res.write ("Say hello.");
Res.end ();
};
Exports.upload = function (res) {
Res.writehead ({"Content-type": "Text/plain"});
Res.write ("Upload");
Res.end ();
};
In cmd, type node index.js to start.
However, the above code is blocked. If you have a createserver callback function, it takes a long time to compute. Then the event polling for Node.js is blocked.
In Nodejs, the key to his efficiency is to quickly return to the event loop.
We will transform the requesthandler.js as follows, in this example, because the event loop has been blocked by the sleep function, resulting in the createserver callback can not return in time.
Copy Code code 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 ({"Content-type": "Text/plain"});
Res.write ("Say hello.");
Res.end ();
};
Exports.upload = function (res) {
Res.writehead ({"Content-type": "Text/plain"});
Res.write ("Upload");
Res.end ();
};
Type Http://localhost:8088/hello first, and then type Http://localhost:8088/upload. You will find that upload does not need to spend too much time, but waits until hello completes.
We are trying to find the method that is invoked asynchronously. For example, upload in formidable, test is non-blocking. Check the formidable source, found that the most critical is the following code:
Copy Code code 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, the head information is parsed and the segment is blocked. But the real upload file is in Req.on (data), is the use of event-driven, non-blocking. In other words, his non-blocking model relies on the entire Nodejs event dispatch schema.
What happens when you consume a lot of computations like sleep, but you can't rely on Nodejs to assign a schema?
Now introduce a method similar to that of HTML5 Webworker.
The requesthandler.js will be transformed as follows:
Copy Code code as follows:
var childprocess = require ("child_process");
Exports.hello = function (res) {
var n = childprocess.fork (__dirname + "/subprocess.js");
N.on (' message ', function () {
Res.writehead ({"Content-type": "Text/plain"});
Res.write ("Say hello.");
Res.end ();
});
N.send ({});
};
Exports.upload = function (res) {
Res.writehead ({"Content-type": "Text/plain"});
Res.write ("Upload");
Res.end ();
};
and join Subprocess.js
Copy Code code 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, upload has returned when Hello is still waiting.
Conclusion:
Probably recently, I read a lot of nodejs articles in the blog park, we all think that Nodejs is asynchronous. But the degree of asynchrony, this concept is not a few articles on the right.
In fact Nodejs, he is a two-tier architecture. C + +, and JavaScript. And it's a single thread. This is particularly important. node is actually C + + using V8 to invoke the JS command, in order to implement the call order to maintain an event sequence. Therefore, within a JS function, his call will definitely block other function. Therefore, the online process.nexttick and settimeout, etc., are not able to generate new threads to ensure that they are not blocked. What he realizes is only the element order problem of the event sequence. The implementation of the Settimeout,process.nexttick is much simpler than the one in which the event sequence is added directly to the top level (there is an incident). The settimeout is adding a C + + thread and adding callback to the event sequence at a specified time
Take the file IO of node as an example. His readfile and other functions, the second argument is a callback. The first thing in node is to record the callback, then call the underlying C + +, call the C + + START process, you can be considered asynchronous. Because it has to C + +, rather than JS this block. Therefore, exec to callback is asynchronous, Http.createserver to trigger callback is asynchronous. There are many, such as MySQL call method, do not know if you have seen the source code, he is the socket to send commands, I believe this process is very fast. Then the process of waiting for the callback node is hidden in C + +, and he is also asynchronous.
And I this article wants to explain is, if again JS end has spends a lot of time operation how to do. In the way I said above, use JS to open the C + + thread, this subprocess.js, not in node's event sequence internal maintenance. is a new thread and therefore does not block other JS function