简体   繁体   中英

How the request response cycle in node js works with external I/O

Complete node.js beginner here. I saw this "hello world" example somewhere

// Load the http module to create an http server.
var http = require('http');

// Configure our HTTP server to respond with Hello World to all requests.
var server = http.createServer(function (request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.end("Hello World\n");
});

// Listen on port 8000, IP defaults to 127.0.0.1
server.listen(8000);

// Put a friendly message on the terminal
console.log("Server running at http://127.0.0.1:8000/");

Really simple code in which the server responds to HTTP requests with a simple HTTP response with plain text "Hello World"

I also ready about a library to make HTTP requests from javascript

http.get(options, function(resp){
  resp.on('data', function(chunk){
    //do something with chunk
  });
}).on("error", function(e){
  console.log("Got error: " + e.message);
});

Here you make an HTTP request with some options and then do something with the response in a callback.

If one was to make such an API request when an HTTP request comes to the node.js server, what happens? Since the flow has to be single threaded, how can one change the state of the response node.js sends to the client in the callback of the HTTP API request? Won't the response be sent to the event loop already by then? How can one simulate synchronous requests in this system so that you can use the response of the API request to send a response to the client?

Since the flow has to be single threaded, how can one change the state of the response node.js sends to the client in the callback of the HTTP API request?

Because the response isn't sent synchronously with the request having been received.

Won't the response be sent to the event loop already by then?

The response isn't sent until you call res.send or similar, which doesn't have to be in the same job from the job queue that triggered your request callback — and frequently isn't.

How can one simulate synchronous requests in this system so that you can use the response of the API request to send a response to the client?

There's no need to, and doing so would kill throughput.

On any given thread (and NodeJS uses only one), JavaScript works on the basis of a job queue : The single JavaScript thread works by picking up a job from the queue, running the code for it all the way through, and then picking up the next job from the queue (or idling until one is added). When an event comes in or similar, if you've set up a handler for that event, a call to your handler is added to the job queue. (There are actually at least two layers to the job queue; see this answer for more on that if you're interested.)

It's absolutely fine if you don't respond to the "We got an HTTP request" from within the code for the job that called your handler. That's perfectly normal. The job and the request are completely disassociated from each other. And so it's fine (and normal) if you start an asynchronous process (like a get , or a readFile ). Later, when the result of that process is available, a new job gets added to the queue, the JavaScript thread picks it up, and you use res.send or similar to reply to the request that's been waiting.

This is how NodeJS manages high throughput despite having only a single thread: If you use asynchronous I/O throughout, your actual code doesn't have to occupy the thread for all that long, because it doesn't wait for the I/O to complete. It can do more work on other things while the I/O is pending, and then respond to it when the I/O completes.

You need to change your code like this:

http.get(options, function(resp){
  resp.on('data', function(chunk){
    resp.send(chunk);
  });
}).on("error", function(e){
  console.log("Got error: " + e.message);
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM