Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/397.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 对后端服务的节点服务器异步调用_Javascript_Node.js_Asynchronous_Axios_Event Loop - Fatal编程技术网

Javascript 对后端服务的节点服务器异步调用

Javascript 对后端服务的节点服务器异步调用,javascript,node.js,asynchronous,axios,event-loop,Javascript,Node.js,Asynchronous,Axios,Event Loop,我是Node的新手,正在编写我的第一个Node服务器。在调用后端rest服务之后,它应该用一个简单的页面响应一个简单的get请求 我正在使用express管理请求,并使用axios软件包进行后端请求。问题是服务器阻塞了事件循环,我在理解如何对后端进行异步调用时遇到了问题 到目前为止,前端服务器一次只能管理一个请求!!我预计,如果后端服务每次回答都需要10秒钟,那么前端服务器可以在10秒钟内回答两个并发请求,而不是在20秒钟内 我哪里错了? 以下是前端节点代码的摘录: app.get('/', f

我是Node的新手,正在编写我的第一个Node服务器。在调用后端rest服务之后,它应该用一个简单的页面响应一个简单的get请求

我正在使用express管理请求,并使用axios软件包进行后端请求。问题是服务器阻塞了事件循环,我在理解如何对后端进行异步调用时遇到了问题

到目前为止,前端服务器一次只能管理一个请求!!我预计,如果后端服务每次回答都需要10秒钟,那么前端服务器可以在10秒钟内回答两个并发请求,而不是在20秒钟内

我哪里错了?

以下是前端节点代码的摘录:

app.get('/', function(req, res) {

      //Making the call to the backend service. This should be asynchronous...
      axios.post(env.get("BACKEND_SERVICE"), 
      { "user": "some kind of input"})
        .then(function(response){

        //do somenthing with the data returned from the backend...

        res.render('homepage');
        })
    }
app.post('/api/getTypes', jsonParser, function (req, res) {

      console.log("> API request for 'api/getTypes' SLEEP");
      var now = new Date().getTime();
      while(new Date().getTime() < now + 10000){ /* do nothing */ }
      console.log("> API request for 'api/getTypes' WAKE-UP");

      res.json({"types":"1"});
    }
这是后端节点代码的定义和提取:

app.get('/', function(req, res) {

      //Making the call to the backend service. This should be asynchronous...
      axios.post(env.get("BACKEND_SERVICE"), 
      { "user": "some kind of input"})
        .then(function(response){

        //do somenthing with the data returned from the backend...

        res.render('homepage');
        })
    }
app.post('/api/getTypes', jsonParser, function (req, res) {

      console.log("> API request for 'api/getTypes' SLEEP");
      var now = new Date().getTime();
      while(new Date().getTime() < now + 10000){ /* do nothing */ }
      console.log("> API request for 'api/getTypes' WAKE-UP");

      res.json({"types":"1"});
    }
app.post('/api/getTypes',jsonParser,function(req,res){
log(“>API请求'API/getTypes'睡眠”);
var now=new Date().getTime();
而(new Date().getTime()API请求'API/getTypes'唤醒”);
res.json({“types”:“1”});
}

问题在于,繁忙的等待会使后端服务器无法开始处理第二个请求

我假设您正在尝试模拟获取类型的过程需要一段时间。很可能您要做的是获取类型将是异步的和I/O绑定的(读取文件、查询数据库等)。要模拟这一过程,只需使用
setTimeout

app.post('/api/getTypes', jsonParser, function (req, res) {

  console.log("> API request for 'api/getTypes' SLEEP");
  setTimeout(function() {
      console.log("> API request for 'api/getTypes' WAKE-UP");
      res.json({"types":"1"});
  }, 10000);
});
这避免了占用后端服务器的唯一线程,使其可以自由地开始对第二个(第三个、第四个……)请求进行重叠处理

这是Node的关键原则之一:如果避免同步,就不要同步进行操作。:-)这就是API如此面向异步的原因

如果您确实在某个时候发现处理请求需要大量的CPU消耗,那么您可能会将其剥离为服务器的子进程,而不是在服务器进程中执行。节点的设计是单线程的,通过强调异步I/O实现了非常高的吞吐量。这对于您需要做的大多数事情来说都非常有效…直到它不起作用为止:-)


请回复您的评论:

后端进程将使用node以外的其他技术编写,它将调用一个DB,这可能需要一段时间。我编写了简单的节点rest服务来模拟这一点。我想了解的是,如果后端需要时间来处理请求,前端服务器将如何反应

花时间处理请求和占用唯一一个忙于等待的服务器线程(或执行大量CPU繁重的工作)之间有很大的区别。您的忙等待模型执行大量CPU繁重的工作,但如果获取类型是在节点外部,您就不会忙着等待它,而是将回调排队等待异步完成(等待子进程的I/O,或连接到第三个服务器进程的套接字的I/O,或等待DB的I/O,等等)。因此,上面的
setTimeout
示例是一个更好的模型,可以说明您真正在做什么

繁忙的等待使前端无法完成,因为它是这样的:

Backend Time Frontend Queue Backend −−−− −−−−−−−−−− −−−−−−−−−−−−−−−−−−−−− −−−−−−−−−−−−−−−−−−−−− 0 sec Request #1 −−−−−−> Receive request #1 −−−−−> Pick up job for request #1 0 sec Request #1 −−−−−−> Receive request #2 Busy wait 10 seconds 10 sec Got #1 back <−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− Send response #1 −−−−−> Pick up job for request #2 Busy wait 10 seconds 20 sec Got #2 back <−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− Send response #2 后端 时间前端队列后端 −−−− −−−−−−−−−− −−−−−−−−−−−−−−−−−−−−− −−−−−−−−−−−−−−−−−−−−− 0秒请求#1−−−−−−> 接收请求#1−−−−−> 按要求领取工作#1 0秒请求#1−−−−−−> 接收请求#2 忙等待10秒 10秒得到#1回<−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− 发送响应#1 −−−−−> 按要求领取工作#2 忙等待10秒 20秒得到2回<−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− 发送响应#2 因此,即使前端没有忙着等待,它也会看到20秒过去了,因为后端忙着为每个请求等待(无法做任何其他事情)10秒


但这不是你真正的设置会做的,除非你使用的其他技术也是单线程的。(如果是,您可能希望有多个类型并行运行。)

是的,上面的代码只是为了模拟获取类型所需的后端过程。后端进程将使用node以外的其他技术编写,它将调用一个DB,这可能需要一段时间。我编写了简单的节点rest服务来模拟这一点。我想了解的是,如果后端需要时间来处理请求,前端服务器将如何反应。@Roberto:我已经在答案的末尾添加了内容。根据您的描述,在获取类型时,后端节点服务器不会陷入繁重的CPU工作。我还解释了为什么前端(不忙等待)会受到后端忙等待的影响。