如何在node.js中完成繁重的处理操作
我有一个沉重的数据处理操作,我需要按照10-12的simulatenous请求完成。 我已经阅读了更高级别的并发性Node.js是一个很好的平台,它通过一个非阻塞事件循环来实现它。
我所知道的是,为了查询数据库等事情,我可以将一个事件产生到一个单独的进程(如mongod
, mysqld
),然后有一个callback来处理这个进程的结果。 很公平。
但是如果我想要在callback中完成一个沉重的计算。 在这个callback中的代码完全执行之前,是不是会阻止其他的请求呢? 例如,我想处理一个高分辨率的图像和代码,我已经在Javascript本身( no separate
过程来做image processing)。
我想实施的方式就像
get_image_from_db(image_id, callback(imageBitMap) { heavy_operation(imageBitMap); // Can take 5 seconds. });
那个heavy_operation
阻止节点接受这5秒的任何请求heavy_operation
? 还是我在想这样做的错误方式呢? 请指导,我是JS新手。
UPDATE
或者可以像我可以处理部分图像,并使事件循环回去采取其他callback,并返回到处理部分图像。 (比如优先事件)。
是的,它会阻止它,因为callback函数在主循环中执行。 它只是asynchronous调用不阻止循环的函数。 这是我的理解,如果你想image processingasynchronous执行,你将不得不使用一个单独的进程来做到这一点。
请注意,您可以编写自己的asynchronous过程来处理它。 开始你可以阅读如何编写Node.js的asynchronous函数的答案。
UPDATE
我如何在node.js中创build一个非阻塞的asynchronous函数? 也可能值得一读。 这个问题实际上是在我链接的另一个引用,但我想我会在这里包括它为简单起见。
不幸的是,我还没有足够的信誉点来评论Nick的答案,但是你看过Node的集群API吗? 目前它仍然是实验性的,但它可以让你产生多个线程。
当一个重要的计算在callback中完成时,事件循环将被阻塞直到计算完成。 这意味着callback会阻塞事件循环5秒钟。
我的解决scheme
可以使用生成器函数来对事件循环进行回退控制。 我将使用一个while loop
运行3秒,以充当长时间运行的callback。
没有发生器function
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
带有发生器function
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生成器可以帮助运行繁重的计算function,当它仍然在计算时,会对事件循环进行控制。
要详细了解事件循环,请访问https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/function*