位于 Promise 链中间的 EventEmitter [英] EventEmitter in the middle of a chain of Promises

查看:22
本文介绍了位于 Promise 链中间的 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
  });

我认为让我的程序工作的唯一方法是重写它以删除承诺链,并在包装​​设置/拆卸的东西中使用原始 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();
  });
});

但是由于 EventEmitter 在整个 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
  });

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

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