SoFunction
Updated on 2025-03-09

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

We want to pass the response object (get from the server's callback function onRequest()) to the request handler through the request routing. The handler can then use the functions on the object to respond to the request.

Let's make modifications first:

Copy the codeThe code is as follows:

var http = require("http");
var url = require("url");
function start(route, handle) {
  function onRequest(request, response) {
 var pathname = ().pathname;
 ("Request for " + pathname + " received.");
 route(handle, pathname, response);
  }
  (onRequest).listen(8888);
  ("Server has started.");
}
= start;

We pass the response object as the third parameter to the route() function, and we remove all the response call in the onRequest() handler because we want this part of the work to let the route() function complete.

Next modify:

Copy the codeThe code is as follows:

function route(handle, pathname, response) {
  ("About to route a request for " + pathname);
  if (typeof handle[pathname] === 'function') {
 handle[pathname](response);
  } else {
 ("No request handler found for " + pathname);
 (404, {"Content-Type": "text/plain"});
 ("404 Not found");
 ();
  }
}
= route;

The same pattern: Compared to the previous acquisition of the return value from the request handler, this time instead, it is directly passed the response object. If there is no corresponding request processor to handle it, we will directly return the "404" error.

Next modify:

Copy the codeThe code is as follows:

var exec = require("child_process").exec;
function start(response) {
  ("Request handler 'start' was called.");
  exec("ls -lah", function (error, stdout, stderr) {
 (200, {"Content-Type": "text/plain"});
 (stdout);
 ();
  });
}
 
function upload(response) {
  ("Request handler 'upload' was called.");
  (200, {"Content-Type": "text/plain"});
  ("Hello Upload");
  ();
}
 
= start;
= upload;

Our handler function needs to receive the response parameter in order to respond directly to the request. The start handler performs a request response operation in the anonymous callback function of exec(), while the upload handler still simply replying to "Hello World", but this time it is using the response object.

If you want to prove that the time-consuming operation in the /start handler does not block the immediate response to the /upload request, you can modify it to the following form:

Copy the codeThe code is as follows:

var exec = require("child_process").exec;
function start(response) {
  ("Request handler 'start' was called.");
  exec("find /",
      { timeout: 10000, maxBuffer: 20000*1024 },
      function (error, stdout, stderr) {
  (200, {"Content-Type": "text/plain"});
  (stdout);
  ();
      }
  );
}
 
function upload(response) {
  ("Request handler 'upload' was called.");
  (200, {"Content-Type": "text/plain"});
  ("Hello Upload");
  ();
}
 
= start;
= upload;

In this way, when requesting http://localhost:8888/start, it will take 10 seconds to load, and when requesting http://localhost:8888/upload, it will respond immediately, even if the /start response is still being processed at this time.