2013-03-10 47 views
2

我有一个繁重的数据处理操作,需要按照10-12的simulatenous请求完成。我已经阅读了更高级别的并发性Node.js是一个很好的平台,它通过一个非阻塞事件循环来实现它。我知道,对于像查询数据库这样的事情,我可以产生一个事件到一个单独的进程(如mongod,mysqld),然后有一个回调来处理该进程的结果。很公平。如何在node.js中完成繁重的处理操作

但是如果我想要在回调中完成大量计算,该怎么办。它会阻止其他请求,直到该回调中的代码完全执行。例如,我想处理一个高分辨率的图像和代码,我已经在Javascript本身(no separate进程做图像处理)。

我想实现的方式是像

get_image_from_db(image_id, callback(imageBitMap) { 
    heavy_operation(imageBitMap); // Can take 5 seconds. 
}); 

将采取在这5秒中的任何请求heavy_operation停止节点。或者我正在考虑错误的方式来完成这样的任务。请指导,我是JS新手。

UPDATE

或者也可以像我可以处理局部图像,使事件循环回去采取其他回调并返回到处理该部分图像。 (比如优先事件)。

回答

3

是的,它会阻止它,因为回调函数在主循环中执行。它只是异步调用的函数,不会阻塞循环。这是我的理解,如果你想图像处理异步执行,你将不得不使用一个单独的进程来做到这一点。

请注意,您可以编写自己的异步过程来处理它。开始你可以阅读How to write asynchronous functions for Node.js的答案。

UPDATE

how do i create a non-blocking asynchronous function in node.js?也可能是值得一读。这个问题实际上是在我链接的另一个引用的,但我想我会将它包括在这里为了简单起见。

+0

但是,如果我有单独的进程为重操作,如果我说的有15个请求进来,会不会它创建15道工序。这将是非常昂贵的。我不喜欢在节点中创建线程。谢谢你的回答。我会接受它,一旦我得到我的怀疑清除:) – 2013-03-10 00:51:04

+0

也检查我的问题中的更新。 – 2013-03-10 00:51:51

+1

是的,它会创建15个进程,并且据我所知,你不能在Node中创建线程。它有一个线程,这是您的主要事件循环。另一个选择是编写一个单独的Node Worker应用程序,它的任务图像处理通过消息队列(RabbitMQ或其他)传递给它。然而,这只会同步处理图像(一次一个)。如果你想让它们同时处理,你将不得不创建独立的进程。 – 2013-03-10 00:59:26

3

很抱歉,我还没有足够的知名度对Nick的评论发表评论,但是你看看Node's cluster API?目前它仍然是实验性的,但它可以让你产生多个线程。

+0

+1感谢您的回答。将研究它:) – 2013-03-10 02:35:43

0

当在回调中完成大量计算时,事件循环将被阻塞,直到计算完成。这意味着回调会阻止事件循环5秒。

我的解决方案

有可能使用一台发电机的功能,产生反馈控制事件循环。我将使用运行3秒的while loop作为长时间运行的回调。

没有发电机功能

let start = Date.now(); 

setInterval(() => console.log('resumed'), 500); 
function loop() { 
    while ((Date.now() - start) < 3000) { //while the difference between Date.now() and start is less than 3 seconds 
     console.log('blocked') 
    } 
} 

loop(); 

输出将是:

// blocked 
// blocked 
// 
// ... would not return to the event loop while the loop is running 
// 
// blocked 
//...when the loop is over then the setInterval kicks in 
// resumed 
// resumed 

与发电机功能

let gen; 
let start = Date.now(); 

setInterval(() => console.log('resumed'), 500); 

function *loop() { 
    while ((Date.now() - start) < 3000) { //while the difference between Date.now() and start is less than 3 seconds 
     console.log(yield output()) 
    } 
} 

function output() { 
    setTimeout(() => gen.next('blocked'), 500) 
} 

gen = loop(); 
gen.next(); 

的输出是:

// resumed 
// blocked 
//...returns control back to the event loop while though the loop is still running 
// resumed 
// blocked 
//...end of the loop 
// resumed 
// resumed 
// resumed 

使用JavaScript生成器可以帮助运行将产量回控制事件循环,同时它还是计算繁重的计算功能。

为了更多地了解事件循环访问 https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/function*

https://davidwalsh.name/es6-generators