//defining schemas, models, db connections, etc..
http.createServer(function (req, res) {
// some irrelevant stuff..
Model.find({name : regex}).exec(function (err, results) {
var localArray = [];
for (var i = 0, len = results.length; i < len; ++i) {
localArray.push(results[i].name);
localArray.push(results[i].id);
}; // is this for loop blocking?
// some more irrelevant stuff..
});
}).listen(8080);
我的回调有一个for循环,可以很长(results.length = 100)。
我是否写过阻止代码?如果是,我怎样才能使其无阻塞?
答案 0 :(得分:3)
长话短说,答案是肯定的,它是封锁的。在此循环运行时收到的任何请求都将排队。使用子进程解锁您的父代码。它要求你的机器是多核的(不是为了产生一个过程而是为了有效)。
长篇故事:
JavaScript(和Node因此)是单线程的。在这个问题的上下文中意味着什么 - 当你循环运行时,不能调用其他函数。 解除阻止的唯一方法是使用子进程。你有两种选择,每种都有它自己的力量和缺点。
第一个选项非常简单,需要您将服务器包装在群集http://nodejs.org/api/cluster.html中 但是,您可能会在每个节点进程中运行此循环来“阻止”整个集群。
第二种选择实施起来更复杂,需要更多资源。但是,当你必须做一些非常沉重和/或可能存在内存泄漏的事情时,这真是令人惊讶。这允许你做的是创建一个单独的Node进程(需要一些RAM并花费几毫秒才能启动,所以你不能产生数百万这些人),传递一些参数并等待结果来。您的父进程将能够提供即将发出的请求。但是一旦完成,不要忘记杀死子进程。 http://nodejs.org/api/child_process.html
无论您选择什么,请注意您仍然在同一台计算机上运行,而您遇到的下一个瓶颈是您的计算机资源。无论如何运行一些基准。对一百个项目进行迭代并不会产生一个孩子,但如果你迭代数千或更多?...
P.S。反向循环运行得更快:
for (var i = results.length; i > 0; i--) {
//Do something
};