如何在 Express 请求处理程序中编写非阻塞异步函数 [重复]
Posted
技术标签:
【中文标题】如何在 Express 请求处理程序中编写非阻塞异步函数 [重复]【英文标题】:How to write non-blocking async function in Express request handler [duplicate] 【发布时间】:2017-08-28 16:37:43 【问题描述】:全部:
我是 Node 异步编程的新手,我想知道如何编写一些 Express 请求处理程序来处理耗时的繁重计算任务而不阻塞 Express 处理后续请求?
我认为 setTimeout 可以将作业置于事件循环中,但它仍然会阻止其他请求:
var express = require('express');
var router = express.Router();
function heavy(callback)
setTimeout(callback, 1);
router.get('/', function(req, res, next)
var callback = function(req, res)
var loop = +req.query.loop;
for(var i=0; i<loop; i++)
for(var j=0; j<loop; j++)
res.send("finished task: "+Date.now());
.bind(null, req, res);
heavy(callback)
);
我想我不明白 setTimeout 是如何工作的(我对 setTimeout 的理解是在 1 毫秒延迟之后,它将在单独的线程/进程中启动回调,而不会阻塞其他重调用),谁能告诉我该怎么做这不会阻止其他对heavy()的请求?
谢谢
【问题讨论】:
【参考方案1】:最好使用 process.nextTick 或 setImmediate 代替 setTimeout(取决于您希望何时运行回调)。但是将长时间运行的代码放入函数中是不够的,因为它仍然会阻塞你的线程,只是一毫秒后。
您需要中断代码并多次运行 setImmediate 或 process.nextTick - 就像在每次迭代中一样,然后从中安排新的迭代。否则你将一无所获。
示例
而不是这样的代码:
var a = 0, b = 10000000;
function numbers()
while (a < b)
console.log("Number " + a++);
numbers();
你可以使用这样的代码:
var a = 0, b = 10000000;
function numbers()
var i = 0;
while (a < b && i++ < 100)
console.log("Number " + a++);
if (a < b) setImmediate(numbers);
numbers();
第一个会阻塞你的线程(并且可能会溢出你的调用堆栈),第二个不会阻塞(或者更准确地说,它会在很短的时间内阻塞你的线程 10000000 次,让其他东西运行在那些时刻之间)。
您还可以考虑生成一个外部进程或在 C/C++ 中编写一个本地插件,您可以在其中使用线程。
更多信息见:
How node.js server serve next request, if current request have huge computation? Maximum call stack size exceeded in nodejs Node; Q Promise delay How to avoid jimp blocking the code node.js NodeJS, Promises and performance【讨论】:
谢谢,你能告诉我为什么在我的情况下,下一个请求仍然被阻止事件我使用 setTimeout?我认为 setTimeout 会选择一个不同的线程来运行该 heavy() 并使 Express 请求处理程序线程空闲。但似乎新的请求无法进来...... @Kuan setTimeout 在同一个线程中运行。它使代码稍后运行,但它仍然会在 setTimeout 回调运行时阻塞主线程和事件循环。您需要进行多个 setTimeouts(或 process.nextTick 或 setImmediate 回调),以使事件循环有机会在这些回调之间进行处理,正如我在回答中已经解释的那样。以上是关于如何在 Express 请求处理程序中编写非阻塞异步函数 [重复]的主要内容,如果未能解决你的问题,请参考以下文章