8

我有一个繁重的数据处理操作,我需要每 10-12 个同步请求完成。我已经读过,对于更高级别的并发,Node.js 是一个很好的平台,它通过非阻塞事件循环来实现它。

我所知道的是,对于查询数据库之类的事情,我可以将一个事件生成到一个单独的进程(如mongod, mysqld),然后有一个回调来处理该进程的结果。很公平。

但是,如果我想在回调中完成大量计算怎么办。在该回调中的代码完全执行之前,它不会阻止其他请求。例如,我想处理高分辨率图像,而我拥有的代码本身就在 Javascript 中(no separate进行图像处理的过程)。

我认为实施的方式就像

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

是否会heavy_operation阻止节点在这 5 秒内接受任何请求。还是我在想错误的方式来完成这项任务。请指导,我是JS新手。

更新

或者是否可以像我可以处理部分图像并让事件循环返回以接收其他回调并返回处理该部分图像。(类似于优先事件)。

4

3 回答 3

5

是的,它会阻止它,因为回调函数是在主循环中执行的。只有异步调用的函数不会阻塞循环。据我了解,如果您希望图像处理异步执行,则必须使用单独的进程来执行此操作。

请注意,您可以编写自己的异步进程来处理它。首先,您可以阅读如何为 Node.js 编写异步函数的答案。

更新

如何在 node.js 中创建非阻塞异步函数?可能也值得一读。这个问题实际上在我链接的另一个问题中被引用,但为了简单起见,我想我会把它包括在这里。

于 2013-03-10T00:34:37.663 回答
4

不幸的是,我还没有足够的声望点来评论尼克的回答,但是你看过Node 的集群 API吗?它目前仍处于试验阶段,但它允许您生成多个线程。

于 2013-03-10T02:00:14.493 回答
4

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

我的解决方案

可以使用生成器函数将控制权交还给事件循环。我将使用一个while loop运行 3 秒的函数作为长时间运行的回调。

没有生成器功能

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

于 2017-06-14T18:56:56.277 回答