2013-12-11 140 views
2

我正在研究一个小的nodejs程序,并且有一些麻烦知道程序的所有异步操作何时完成。同步异步创建的承诺

现在,该程序执行下列步骤:

1 /产卵与一些参数的处理。此过程将在其stdout上打印数据。

2 /监听进程stdout“data”事件,每次打印某些内容时,程序都会使用这些数据调用一个函数(我们将称之为“进程”)。

3 /此过程函数最终将数据插入到mongo数据库并发送消息到amqp服务器。

3 /当没有更多的数据时,程序空闲,因为与amqp和mongo数据库的连接仍然存在,所以我需要知道何时完成所有工作才能关闭连接。

所以,我试图使用when.js来使用承诺,但我不能让它为我想要实现的目标而工作。

我让“process”函数返回一个promise,当mongodb insert和amqp消息发送完成后,这个promise就会被解析。 在我的程序中,我创建了一个数组,它将接收所有可以调用when.all()以了解它们何时全部解析的承诺。

但是,由于我在生成的进程将数据打印到其标准输出流时异步创建了承诺,所以对when.all()的调用是使用看起来立即解决的空数组创建的。

下面是一个代码示例,它说明什么我实现:

var when = require('when') 
    , _ = require('lodash') 
    , cp = require('child_process'); 

var promises = []; 

function process(data) { 
    var deferred = when.defer(); 

    setTimeout(function() { 
     deferred.resolve(true); 
    }, 3000); // Let's say we need 3 seconds to process and save data 

    return deferred.promise; 
} 

var ls = cp.spawn('ls', ['-la', '/usr/bin']); 
ls.stdout.on('data', function (data) { 
    console.log('Received data, creating a promise to notify when this data is processed.'); 
    promises.push(process(data)); 
}); 

when.all(promises).then(function (values) { 
    console.log('All promises are now resolved', values); 
}); 

正如你可能已经猜到了,这个程序的输出是:

All promises are now resolved [] 
Received data, creating a promise to notify when this data is processed. 
Received data, creating a promise to notify when this data is processed. 
Received data, creating a promise to notify when this data is processed. 
Received data, creating a promise to notify when this data is processed. 
Received data, creating a promise to notify when this data is processed. 
Received data, creating a promise to notify when this data is processed. 
Received data, creating a promise to notify when this data is processed. 
Received data, creating a promise to notify when this data is processed. 
Received data, creating a promise to notify when this data is processed. 

有没有什么办法,使此代码以预期顺序(最后打印第一行)打印控制台消息样本?

谢谢。

+2

把'when.all()'调用** **里面的'的setTimeout()'处理程序。 – Pointy

+0

我不能这样做,否则它将不符合程序的实际代码,使用衍生进程并监听其标准输出“数据”事件。第二个setTimeout是对这个事件的模拟。在我的真实程序中,你必须想象这将被多次调用。多次调用when.all()来调用它没有意义吗?或者我错过了什么? –

+1

在承诺存在之前调用'when.all()'没有任何意义。当您启动异步操作时,这些承诺会同步出现。我认为你的“测试”设置是真正的问题 - 你的'setTimeout()'调用本身没有返回一个承诺,而是一个真正的异步操作。 – Pointy

回答

2

只有在完成所有承诺后您才需要致电。在你的评论中提到:

我想,当一切都做这样

这是不正确我不知道。您可以知道一切时使用close事件进行:

ls.on('close',function(){ 
    when.all(promises).then(function (values) { 
     console.log('All promises are now resolved', values); 
    }); 
}); 
+0

啊,对。我现在感到非常愚蠢。谢谢 :) –