【问题标题】:Synchronize promises created asynchronously同步异步创建的 Promise
【发布时间】:2013-12-29 14:38:13
【问题描述】:

我正在开发一个nodejs小程序,不知道程序的所有异步操作何时完成。

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

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

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

3/ 这个处理函数最终会将数据插入到一个mongo数据库中,并向一个amqp服务器发送消息。

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

所以,我尝试使用 when.js 来使用 Promise,但我无法让它实现我想要实现的目标。

我让“进程”函数返回一个promise,当mongodb insert 和amqp 消息发送完成时,它将被解决。 在我的程序中,我正在创建一个数组,它将接收所有能够调用 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.

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

谢谢。

【问题讨论】:

  • when.all() 调用放入 setTimeout() 处理程序中。
  • 我不能这样做,否则它将不符合程序的真实代码,使用生成的进程并监听其标准输出“数据”事件。第二个 setTimeout 是这个事件的模拟。在我的真实程序中,您必须想象这将被多次调用。多次调用 when.all() 没有意义吗?还是我错过了什么?
  • 在 Promise 存在之前调用 when.all() 是没有意义的。当您开始一个异步操作时,promise 会同步存在。我认为您的“测试”设置是真正的问题 - 您的 setTimeout() 调用本身没有返回承诺,而是真正的异步操作。
  • 尖利完全正确。 Promise,顾名思义,是现在承诺在未来做点什么。 “promise made asyncronous”的概念看起来很奇怪。
  • 谢谢你们的回答。那很有帮助。我更新了我的代码示例以反映我的真实用例,如您所见,如果测试设置是问题,那么实际用例也是同样的问题。我无法提前创建承诺,因为我不知道生成的进程将返回什么。好吧,我想我不知道什么时候一切都以这种方式完成。再次感谢!

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


【解决方案1】:

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

我想我不知道什么时候一切都以这种方式完成

这是不正确的。您可以使用close 事件知道一切何时完成:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-29
    • 2016-11-08
    • 2017-12-24
    • 2021-02-15
    • 2023-02-24
    • 2018-05-01
    • 2018-03-12
    相关资源
    最近更新 更多