Easily create nodejs server (9) : implement non blocking operations

  • 2020-05-07 19:10:38
  • OfStack

We want to pass the response object (retrieved from the server's callback function onRequest()) through the request route to the request handler. The handler can then respond to the request with functions on that object.

First, we modify server.js:


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;

We pass the response object to the route() function as the third argument, and we remove all the response function calls from the onRequest() handler because we want the route() function to do the work.

Next, modify router.js:


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;

Same pattern: instead of getting the return value from the request handler, pass the response object directly. If there is no corresponding request handler, we simply return a "404" error.

Next, modify requestHandler.js:


var exec = require("child_process").exec;
function start(response) {
  console.log("Request handler 'start' was called.");
  exec("ls -lah", 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;

Our handler function needs to receive the response parameter in order to respond directly to the request. The start handler does the request response in the anonymous callback function of exec(), while the upload handler simply replies "Hello World", only this time using the response object.

If you want to demonstrate that a time-consuming operation in the /start handler does not block an immediate response to the /upload request, you can modify requestHandlers.js as follows:


var exec = require("child_process").exec;
function start(response) {
  console.log("Request handler 'start' was called.");
  exec("find /",
      { timeout: 10000, maxBuffer: 20000*1024 },
      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;

So 1, when the request http: / / localhost: 8888 / start, it will take ten seconds to load, and when the request http: / / localhost: 8888 / upload, will respond immediately, even if this time/start response is still in processing.


Related articles: