同步异步创建的promises

时间:2013-12-11 14:51:24

标签: javascript node.js asynchronous promise when-js

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

目前,该计划执行以下步骤:

1 /使用一些参数生成进程。此过程将在其标准输出上打印数据。

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

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

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

所以,我尝试使用when.js来使用promises,但我不能让它适用于我想要实现的目标。

我使“进程”函数返回一个promise,当mongodb insert和amqp message发送完成时将解析。 在我的程序中,我正在创建一个数组,该数组将接收所有可以调用when.all()以确定它们何时全部被解析的承诺。

但是,由于我在生成的进程将数据打印到stdout流时异步创建promises,因此使用空数组调用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.

有没有办法按预期顺序(最后打印第一行)制作此代码示例打印控制台消息?

感谢。

1 个答案:

答案 0 :(得分:2)

只有在完成所有承诺后才需要打电话。在您的评论中,您提到过:

  

我想我不知道什么时候这样做了

哪个不对。您可以知道何时使用close事件完成所有操作:

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