EventEmitter в середине цепочки Promises
Я делаю то, что включает в себя последовательность последовательности 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) 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();
});
});
Но так как EventEmitters настолько распространены во всех Node.js, я не могу не думать, что я должен быть способен заставить их работать в цепочках Promise. Любые подсказки?
На самом деле, одна из причин, по которой я хочу использовать Bluebird, заключается в том, что я хочу использовать функции аннулирования, чтобы разрешить отмену текущей команды извне.
Ответы
Ответ 1
Существует два подхода: один предоставляет синтаксис, который вы изначально запрашивали, а другой - делегаты.
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
});