nodeJs官方的说法是:在nodeJs中除了代码,所有一切都是并行的。也就是说可以在不新增进程的情况下,依然可以对任务进行并行处理。
实现的方式就是通过事件轮询,当然这也不是个简单的事情,要使用事件轮询就需要使用回调,将函数作为参数传递给其他需要花时间做处理的函数(比如复杂逻辑)。
简单的一句话就是:nodeJs非阻塞是通过轮询回调事件实现的。
处理复杂逻辑时,如果不做处理,会阻塞掉进程,导致其他请求不能执行(nodeJs时单进程),所以对这类逻辑用异步处理,都是请求时同步执行的,异步的结果无法返回给用户,就必须采用异步回调的方式,子进程执行完成后回调传入的回调函数,确保结果正常返回,同时避免进程阻塞。
先来看一个错误的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | var exec = require("child_process").exec; function start() { console.log("Request handler 'start' was called."); var content = "empty"; exec("find /", function (error, stdout, stderr) { content = stdout; }); return content; } function upload() { console.log("Request handler 'upload' was called."); return "Hello Upload"; } exports.start = start; exports.upload = upload; |
“find /”是非常耗时的,我们这里通过exec()开启一个子进程去执行,但是return content是同步执行的,返回值会是”empty”。这时需要对这个子进程写入回调,让子进程执行完后回调返回结果。
代码修改一下:
server.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | var http = require("http"); var url = require("url"); function start(route, handle) { function onRequest(request, response) { var pathname = url.parse(request.url).pathname; console.log("Request for " + pathname + " received."); route(handle, pathname, response); } http.createServer(onRequest).listen(8888); console.log("Server has started."); } exports.start = start; |
router.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | function route(handle, pathname, response) { console.log("About to route a request for " + pathname); if (typeof handle[pathname] === 'function') { handle[pathname](response); } else { console.log("No request handler found for " + pathname); response.writeHead(404, {"Content-Type": "text/plain"}); response.write("404 Not found"); response.end(); } } exports.route = route; |
requestHandler.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | var exec = require("child_process").exec; function start(response) { console.log("Request handler 'start' was called."); exec("find /", function (error, stdout, stderr) { response.writeHead(200, {"Content-Type": "text/plain"}); response.write(stdout); response.end(); }); } function upload(response) { console.log("Request handler 'upload' was called."); response.writeHead(200, {"Content-Type": "text/plain"}); response.write("Hello Upload"); response.end(); } exports.start = start; exports.upload = upload; |
这里把response作为回调函数,确保子进程执行完后回调返回数据。
转载请注明:迷路的老鼠 » nodeJs非阻塞的实现