Node JS Express Handling multiple requests

2019-03-04 00:58发布

What I Have: I have a nodejs express server get endpoint that in turn calls other APIs that are time consuming(say about 2 seconds). I have called this function with a callback such that the res.send is triggered as a part of the call back. The res.send object packs an object that will be created after the results from these time consuming API calls is performed. So my res.send can only be sent when I have the entire information from the API call.

Some representative code.

someFunctionCall(params, callback)
{
  // do some asyncronous requests.
  Promise.all([requestAsync1(params),requestAsync2(params)]).then
  {
     // do some operations
     callback(response) // callback given with some data from the promise
  }

}
app.get('/',function(req, res){
 someFunctionCall(params, function(err, data){
    res.send(JSON.stringify(data))
   }
}

What I want I want my server to be able to handle other parallel incoming get requests without being blocked due to the REST api calls in the other function. But the problem is that the callback will only be issued when the promises are fulfilled,each of those operations are async, but my thread will wait till the execution of all of them. And Node does not accept the next get request without executing the res.send or the res.end of the previous request. This becomes an issues when I have multiple requests coming in, each one is executed one after another.

Note: I do not want to go with the cluster method, I just want to know if it is possible to this without it.

1条回答
Melony?
2楼-- · 2019-03-04 01:50

You are apparently misunderstanding how node.js, asynchronous operations and promises work. Assuming your long running asynchronous operations are all properly written with asynchronous I/O, then neither your requestAsync1(params) or requestAsync2(params) calls are blocking. That means that while you are waiting for Promise.all() to call its .then() handler to signify that both of those asynchronous operations are complete, node.js is perfectly free to run any other events or incoming requests. Promises themselves do not block, so the node.js event system is free to process other events. So, you either don't have a blocking problem at all or if you actually do, it is not caused by what you asked about here.

To see if your code is actually blocking or not, you can temporarily add a simple timer that outputs to the console like this:

let startTime;
setInterval(function() {
    if (!startTime) {
        startTime = Date.now();
    }
    console.log((Date.now() - startTime) / 1000);
}, 100)

This will output a simple relative timestamp every 100ms when the event loop is not blocked. You would obviously not leave this in your code for production code, but it can be useful to show you when/if your event loop is blocked.


I do see an odd syntax issue in the code you included in your question. This code:

someFunctionCall(params, callback)
{
  // do some asyncronous requests.
  Promise.all([requestAsync1(params),requestAsync2(params)]).then
  {
     // do some operations
     callback(response) // callback given with some data from the promise
  }

}

should be expressed like this:

someFunctionCall(params, callback)
{
  // do some asyncronous requests.
  Promise.all([requestAsync1(params),requestAsync2(params)]).then(function(response)
  {
     // do some operations
     callback(response) // callback given with some data from the promise
  }

});

But, an even better design would be to just return the promise and not switch back to a plain callback. Besides allowing the caller to use the more flexible promises scheme, you are also "eating" errors that may occur in either or your async operations. It's suggest this:

someFunctionCall(params) {
  // do some asyncronous requests.
    return Promise.all([requestAsync1(params),requestAsync2(params)]).then(function(results) {
        // further processing of results
        // return final resolved value of the promise
        return someValue;
    });
}

Then, then caller would use this like:

someFunctionCall(params).then(function(result) {
    // process final result here
}).catch(function(err) {
    // handle error here
});
查看更多
登录 后发表回答