承诺链中间的EventEmitter [英] EventEmitter in the middle of a chain of Promises

查看:71
本文介绍了承诺链中间的EventEmitter的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在做的事情涉及依次运行child_process.spawn()序列(进行一些设置,然后运行调用者感兴趣的实际命令),然后进行一些清理.

I am doing something that involves running a sequence of child_process.spawn() in order (to do some setup, then run the actual meaty command that the caller is interested in, then do some cleanup).

类似的东西:

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()返回给调用者.

Internally I'm using child_process.spawn(), which returns an EventEmitter and I'm effectively returning the result of the close event from runInterestingCommand() back to the caller.

现在,我还需要从stdout和stderr向调用方发送data事件,这些事件也来自EventEmitters.是否有办法使(Bluebird)Promises发挥作用,还是只是阻碍了发出多个事件的EventEmitters?

Now I need to also send data events from stdout and stderr to the caller, which are also from EventEmitters. Is there a way to make this work with (Bluebird) Promises, or are they just getting in the way of EventEmitters that emit more than one event?

理想情况下,我希望能够写:

Ideally I'd like to be able to write:

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,例如:

The only way I can think to make my program work is to rewrite it to remove the promise chain and just use a raw EventEmitter inside something that wraps the setup/teardown, something like:

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链中工作.有任何线索吗?

But then since EventEmitters are so common throughout Node.js, I can't help but think I should be able to make them work in Promise chains. Any clues?

实际上,我想继续使用Bluebird的原因之一是因为我想使用取消"功能来允许从外部取消正在运行的命令.

Actually, one of the reasons I want to keep using Bluebird, is because I want to use the Cancellation features to allow the running command to be cancelled from the outside.

推荐答案

有两种方法,一种提供您最初要求的语法,另一种采用委托.

There are two approaches, one provides the syntax you originally asked for, the other takes delegates.

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

哪些可以让您使用所需的语法:

Which would let you use your desired syntax:

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这在某种程度上具有误导性,可能需要将代表传递给:

However, IMO this is somewhat misleading and it might be desirable to pass the delegates in:

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

这篇关于承诺链中间的EventEmitter的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆