一尘不染

Node JS Express处理多个请求

node.js

我所拥有的: 我有一个nodejs
express服务器获取端点,该端点依次调用其他耗时的API(例如大约2秒)。我已经通过回调调用了此函数,使得res.send作为回调的一部分被触发。res.send对象打包了一个对象,该对象将在执行这些耗时的API调用的结果之后创建。因此,仅当我从API调用中获得全部信息时,才能发送我的res.send。

一些代表性的代码。

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))
   }
}

我要什么 我希望我的服务器能够处理其它并行输入的GET请求不会被阻挡由于其他功能的REST
API调用。但是问题在于,仅当实现了promise时才会发出回调,这些操作中的每一个都是异步的,但是我的线程将等到所有的操作都执行完毕。并且Node不执行下一个请求的res.send或res.end,就不接受下一个get请求。当我有多个请求进入,每个请求一个接一个地执行时,这成为一个问题。

注意:我不想使用cluster方法,我只是想知道如果没有它,是否有可能做到这一点。


阅读 1024

收藏
2020-07-07

共1个答案

一尘不染

您显然误会了node.js,异步操作和Promise的工作方式。假设长时间运行的异步操作均已使用异步I /
O正确编写,那么您的requestAsync1(params)requestAsync2(params)调用都不会阻塞。这意味着,在等待Promise.all()调用其.then()处理程序以表明这两个异步操作均已完成时,node.js完全可以自由运行任何其他事件或传入请求。承诺本身不会阻塞,因此node.js事件系统可以自由处理其他事件。因此,您根本就没有阻塞问题,或者实际上没有阻塞问题,这不是您在此处询问的原因引起的。

要查看您的代码是否实际被阻塞,可以临时添加一个简单的计时器,将其输出到控制台,如下所示:

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

当事件循环未阻塞时,这将每100ms输出一个简单的相对时间戳。您显然不会在生产代码中将其保留在代码中,但是当事件循环被阻止时,向您显示可能会很有用。


我确实在您的问题中包含的代码中看到了一个奇怪的语法问题。这段代码:

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
  }

}

应该这样表示:

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
  }

});

但是,更好的设计将是仅返回诺言,而不切换回简单的回调。除了允许调用者使用更灵活的Promise方案外,您还“吃”了异步操作或异步操作中可能发生的错误。建议这样做:

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;
    });
}

然后,呼叫者会这样使用:

someFunctionCall(params).then(function(result) {
    // process final result here
}).catch(function(err) {
    // handle error here
});
2020-07-07