react nodejs node method library example node.js promise bluebird

node.js - nodejs - node js events example



EventEmitter en medio de una cadena de Promesas (1)

Hay dos enfoques, uno proporciona la sintaxis que solicitó originalmente y el otro toma delegados.

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; }

Lo que le permitiría usar la sintaxis deseada:

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 });

Sin embargo, en mi opinión, esto es un tanto engañoso y podría ser conveniente pasar a los delegados en:

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; }

Lo que te dejaría hacer:

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 });

Estoy haciendo algo que implica ejecutar una secuencia de child_process.spawn() en orden (para realizar una configuración, luego ejecutar el comando carnoso real en el que está interesado el interlocutor, luego hacer una limpieza).

Algo como:

doAllTheThings() .then(function(exitStatus){ // all the things were done // and we''ve returned the exitStatus of // a command in the middle of a chain });

Donde doAllTheThings() es algo como:

function doAllTheThings() { runSetupCommand() .then(function(){ return runInterestingCommand(); }) .then(function(exitStatus){ return runTearDownCommand(exitStatus); // pass exitStatus along to return to caller }); }

Internamente, estoy usando child_process.spawn() , que devuelve un EventEmitter y efectivamente EventEmitter el resultado del evento close de runInterestingCommand() al interlocutor.

Ahora también necesito enviar eventos de data de stdout y stderr a la persona que llama, que también son de EventEmitters. ¿Hay alguna manera de hacer que esto funcione con las promesas (de Bluebird), o solo están impidiendo que los EventEmitters emitan más de un evento?

Idealmente me gustaría poder escribir:

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 });

La única forma en que puedo pensar para hacer que mi programa funcione es reescribirlo para eliminar la cadena de promesa y simplemente usar un EventEmitter sin procesar dentro de algo que envuelve la configuración / desmontaje, algo como:

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(); }); });

Pero luego, dado que los EventEmitters son tan comunes en Node.js, no puedo evitar pensar que debería poder hacer que funcionen en las cadenas Promise. ¿Alguna pista?

En realidad, una de las razones por las que quiero seguir usando Bluebird es que quiero usar las funciones de cancelación para permitir que el comando de ejecución se cancele desde el exterior.