并行执行一个函数,同时完成其余代码的执行

时间:2013-07-24 17:39:01

标签: node.js

我在nodejs中有一个代码片段,如下所示:

每隔2秒

,将调用foo()。

function foo() 
{
    while (count < 10) 
    {
        doSometing()
        count ++;``
     }
}

doSomething()
{
   ...
}

限制是,foo()没有回调。 如何使while循环执行和foo()完成而不等待dosomething()完成(调用dosomething()并继续),并且dosomething()并行执行?

1 个答案:

答案 0 :(得分:0)

我想,你想要的是:

function foo() 
{
    while (count < 10) 
    {
        process.nextTick(doSometing);
        count ++;
     }
}

process.nextTick将安排在事件循环的下一个刻度上执行doSometing。因此,不是立即切换到doSometing,而是只安排执行并首先完成foo

您也可以尝试setTimeout(doSometing,0)setImmediate(doSometing)。他们将允许I/O调用在doSometing执行之前发生。

将参数传递给doSomething

如果您想将某些参数传递给doSomething,那么最好确保它们将被封装,并且在doSomething执行之前不会更改:

setTimeout(doSometing.bind(null,foo,bar),0);

在这种情况下,即使doSometingfoo将被更改或删除,也会使用正确的参数调用bar。但是,如果foo是一个对象并且你改变了它的一个属性,这将不起作用。

替代方案是什么?

如果您希望doSomething并行执行(不只是异步,而是实际并行),那么您可能对某些作业处理解决方案感兴趣。我建议你看看kickq

var kickq = require('kickq');

kickq.process('some_job', function (jobItem, data, cb) {
  doSomething(data);
  cb();
});

// ...

function foo() 
{
    while (count < 10) 
    {
        kickq.create('some_job', data);
        count ++;
     }
}

kickq.process将创建一个单独的流程来处理您的工作。因此,kickq.create将只注册要处理的作业。

kickq使用redis对作业进行排队,没有它就无法工作。

使用node.js内置模块

另一种方法是使用Child Process构建自己的作业处理器。生成的代码可能如下所示:

var fork = require('child_process').fork,
    child = fork(__dirname + '/do-something.js');

// ...

function foo() 
{
    while (count < 10) 
    {
        child.send(data);
        count ++;
     }
}

do-something.js这是一个单独的.js文件,其中包含doSomething个逻辑:

process.on('message', doSomething);

实际代码可能更复杂。

你应该注意的事情

Node.js是单线程的,因此它一次只执行一个函数。它也不能使用多个CPU。

Node.js是异步的,因此它能够通过在它们之间切换来一次处理多个功能。在处理具有大量I/O调用的函数时,它非常有效,因为它是更新的块。因此,当一个函数等待来自DB的响应时,执行另一个函数。但node.js不是阻止CPU利用率过高的任务的好选择。

可以使用child_processcluster等模块在node.js中进行真正的并行计算。 child_process允许您启动新的node.js进程。它还在父进程和子进程之间创建通信通道。群集允许您运行相同进程的群集。当您处理http个请求时,它非常方便,因为cluster可以在工作人员之间随机分配它们。因此,可以创建一个并行处理数据的工作者集群,但通常node.js是单线程的。