【发布时间】:2014-10-02 16:36:33
【问题描述】:
我正在做一些涉及按顺序运行child_process.spawn() 序列的事情(进行一些设置,然后运行调用者感兴趣的实际命令,然后进行一些清理)。
类似:
doAllTheThings()
.then(function(exitStatus){
// all the things were done
// and we've returned the exitStatus of
// a command in the middle of a chain
});
doAllTheThings() 类似于:
function doAllTheThings() {
runSetupCommand()
.then(function(){
return runInterestingCommand();
})
.then(function(exitStatus){
return runTearDownCommand(exitStatus); // pass exitStatus along to return to caller
});
}
在内部,我使用child_process.spawn(),它返回一个EventEmitter,并且我有效地将close事件的结果从runInterestingCommand()返回给调用者。
现在我还需要将来自 stdout 和 stderr 的 data 事件发送给同样来自 EventEmitters 的调用者。有没有办法使用 (Bluebird) Promises 来完成这项工作,或者它们只是妨碍了发出多个事件的 EventEmitters?
理想情况下,我希望能够写作:
doAllTheThings()
.on('stdout', function(data){
// process a chunk of received stdout data
})
.on('stderr', function(data){
// process a chunk of received stderr data
})
.then(function(exitStatus){
// all the things were done
// and we've returned the exitStatus of
// a command in the middle of a chain
});
我认为让我的程序工作的唯一方法是重写它以删除承诺链,并在包装设置/拆卸的东西中使用原始 EventEmitter,例如:
withTemporaryState(function(done){
var cmd = runInterestingCommand();
cmd.on('stdout', function(data){
// process a chunk of received stdout data
});
cmd.on('stderr', function(data){
// process a chunk of received stderr data
});
cmd.on('close', function(exitStatus){
// process the exitStatus
done();
});
});
但是由于 EventEmitter 在整个 Node.js 中如此普遍,我不禁认为我应该能够使它们在 Promise 链中工作。有什么线索吗?
其实我想继续使用 Bluebird 的原因之一,是因为我想使用 Cancellation 功能,让正在运行的命令可以从外部取消。
【问题讨论】:
-
请查看 Bluebird API 文档中有关进度的文档以及如何处理该问题。
-
@BenjaminGruenbaum 文档说 API 已被弃用,不应使用,但它似乎也没有回答我提出的问题?我没有跟踪进度,我只是有多个事件被触发并且需要能够处理所有事件。
-
那里的解决方案(进度的替代方案)应该适合您的情况。 Promise 不是事件发射器 - 拥有一个事件发射器并使用 Promise 来跟踪完成情况。
-
我遇到了同样的问题,我找到了一篇关于这种模式的好博文:datchley.name/promise-patterns-anti-patterns。你可以向下滚动到中间的“Executing Promises in Series”。