Javascript 发送响应并继续执行任务Express | Node.js

Javascript 发送响应并继续执行任务Express | Node.js,javascript,node.js,express,asynchronous,Javascript,Node.js,Express,Asynchronous,在Node.js(我是新手)中,我试图在收到响应后执行一系列任务。但是,我想让响应时间尽可能快。我不需要将这些任务的结果返回给客户机,因此我尝试立即返回响应 我目前的实施大致如下: var requestTime = Date.now; app.post('/messages', function (req, res) { console.log("received request"); // handle the response var body = res.body;

在Node.js(我是新手)中,我试图在收到响应后执行一系列任务。但是,我想让响应时间尽可能快。我不需要将这些任务的结果返回给客户机,因此我尝试立即返回响应

我目前的实施大致如下:

var requestTime = Date.now; 

app.post('/messages', function (req, res) {
  console.log("received request");

  // handle the response
  var body = res.body;
  res.send('Success');
  res.end();
  console.log("sent response");

  performComplexTasks(body)
})

function performComplexTasks(body){
   // perform data with body data here;
   console.log("finished tasks:", Date.now()-requestTime, "ms");
}

// -------LOG-----------
//    received request
//    POST /api/messages 200 3.685 ms - 59
//    sent response
//    finished tasks: 2500ms
发出请求的客户端似乎一直挂起,直到performComplexTasks()完成。(POST在3.685毫秒内完成,但响应需要2500毫秒才能完成。)


有没有一种方法可以在不让客户端等待/挂起的情况下立即发送响应并完成其他任务?(在我的情况下,客户端不能进行多个API调用。)

您试图在
performComplexTasks
中执行CPU密集型作业,对吗?如果是这样,则该任务将锁定事件循环,新请求将等待作业完成

在node.js中,在与http服务器相同的进程中执行此类“复杂”任务是一种不好的做法。考虑使用后台工作者、队列或类似的东西。< /P>
有关详细信息,请参阅本主题:

如果您的作业不是超级CPU密集型的,并且您可以容忍在主服务器线程上进行某些工作,那么只需使用
wait
中断执行,以便正确发送请求。您可以使用
setTimeout
wait

// This line is wrong too - ask a separate question if needed
var requestTime = Date.now; 

app.post('/messages', async function (req, res) {
  console.log("received request");

  // handle the response
  var body = res.body;
  res.status(200).send({ success: true });
  console.log("sent response");

  // Method 1:
  await performComplexTasks(body)

  // Method 2:
  setTimeout(() => performComplexTasks(body), 0);
})

async function performComplexTasks(body){
   // The line below is required if using the `await` method -
   // it breaks execution and allows your previous function to
   // continue, otherwise we will only resume the other function after
   // this function is completed.
   await new Promise(resolve => setTimeout(resolve, 1));

   // perform data with body data here;
   console.log("finished tasks:", Date.now()-requestTime, "ms");
}

这不是一个非常好的解决方案,您需要使用工作线程进行长时间的操作。

您所拥有的应该可以正常工作?只要响应在服务器上结束,之后发生的事情就不会影响浏览器。@adeneo我已经在本地使用CURL进行了测试,响应时间为
200-15000ms
。当我注释掉performComplexTasks(body)时,响应大约需要
10ms
。所有其他API端点(没有长任务)似乎都更快。这可能是因为一个独立的问题(即,我的服务器CPU使用情况,而不是正确处理
req
res
)?如果是这样,您对我应该从哪里开始调查有什么建议吗?@adeneo另外,如果有问题,这个端点将被另一台服务器(不是浏览器)调用。请尝试
res.status(200)。发送('Success')
并删除
res.end
,然后在超时或下一步尝试包装
performComplexTasks()
?我不知道这是否有什么不同,但这是我要开始的。这是真的,但OP的代码应该结束响应,然后执行阻止工作,以便新请求必须等待等。它不应该阻止已收到响应的当前请求。@没有危险当您刚刚启动express app时,第一个发布/消息的请求会怎么样?工作速度快吗?@无危险您确定其他端点不受影响吗?你在打电话给POST/messages之前和之后有没有给他们打过电话?同时确保performComplexTasks函数没有任何“全局”变量/锁(在请求之间共享),如果这种方法有效(将很快测试),那么即使您的任务是cpu密集型任务,您也可以将cpu密集型任务移动到不同的端点(可能在不同的服务器上或无服务器上),并在这个处理程序的末尾向该端点发送一个网络请求,这将减轻主线程的cpu密集型工作——它将把它变成一个易于并行的异步调用。当然,您希望将单独的performComplexTasks处理程序设为幂等,这样,如果其他人访问该端点,它就不会破坏任何内容。