0

我在nodejs中有一个这样的代码片段:

每 2 秒, foo() 将被调用一次。

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

doSomething()
{
   ...
}

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

4

1 回答 1

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);

在这种情况下doSometing,即使将被更改或删除foo,也会使用正确的参数调用。但是如果 if是一个对象并且您更改了它的一个属性,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_processclusternode.js等模块可以进行真正的并行计算。允许您开始一个新的进程。它还创建了父进程和子进程之间的通信通道。集群允许您运行相同进程的集群。当您处理请求时,它真的很方便,因为可以在工作人员之间随机分配它们。因此,可以创建一个并行处理数据的工作人员集群,尽管通常是单线程的。child_processnode.jshttpclusternode.js

于 2013-07-24T19:34:04.670 回答