我正在做一些事情,涉及按顺序运行一系列 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()
返回给调用者。
现在我还需要将 data
事件从 stdout 和 stderr 发送到调用者,这些事件也来自 EventEmitters。有没有一种方法可以使这项工作与(Bluebird)Promise 一起工作,或者它们只是妨碍发出多个事件的 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
});
我能想到的让我的程序工作的唯一方法是重写它以删除 promise 链,并在包装设置/拆卸的内容中使用原始 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();
});
});
但是由于 EventEmitters 在 Node.js 中如此常见,我忍不住想我应该能够让它们在 Promise 链中工作。有什么线索吗?
实际上,我想继续使用 Bluebird 的原因之一,是因为我想使用取消功能来允许从外部取消正在运行的命令。
最佳答案
有两种方法,一种提供您最初要求的语法,另一种采用委托(delegate)。
function doAllTheThings(){
var com = runInterestingCommand();
var p = new Promise(function(resolve, reject){
com.on("close", resolve);
com.on("error", reject);
});
p.on = function(){ com.on.apply(com, arguments); return p; };
return p;
}
这可以让您使用所需的语法:
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
});
但是,IMO 这有点误导,可能需要通过以下代表:
function doAllTheThings(onData, onErr){
var com = runInterestingCommand();
var p = new Promise(function(resolve, reject){
com.on("close", resolve);
com.on("error", reject);
});
com.on("stdout", onData).on("strerr", onErr);
return p;
}
这会让你这样做:
doAllTheThings(function(data){
// process a chunk of received stdout data
}, 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
});
关于node.js - EventEmitter 位于 Promise 链的中间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36115047/