同步异步创建的承诺

Synchronize promises created asynchronously

本文关键字:承诺 创建 异步 同步      更新时间:2024-07-02

我正在开发一个小的nodejs程序,当程序的所有异步操作都完成时,我会遇到一些麻烦。

目前,该程序执行以下步骤:

1/生成具有一些参数的进程。此进程将在其stdout上打印数据。

2/听processstdout"data"事件,每次打印东西时,程序都会使用数据调用一个函数(我们称之为"process")。

3/这个过程函数最终会将数据插入mongo数据库,并向amqp服务器发送消息。

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

所以,我试着用when.js来利用承诺,但我无法让它实现我想要实现的目标。

我让"process"函数返回了一个promise,这个promise将在mongodb插入和amqp消息发送完成后得到解决。在我的程序中,我正在创建一个数组,它将收到所有的承诺,能够在when.all()时调用,以知道它们何时都被解析。

但是,由于我在派生进程将数据打印到其stdout流时异步创建promise,所以对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.

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

谢谢。

只有在做出所有承诺后,才需要调用。您在评论中提到:

我想我不知道什么时候一切都是这样做的

这是不正确的。您可以知道何时使用close事件完成所有操作:

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