node.js - EventEmitter 位于 Promise 链的中间

标签 node.js promise bluebird

我正在做一些事情,涉及按顺序运行一系列 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/

相关文章:

node.js - 在NodeJS Controller 中处理多个错误检查

javascript - 达到值后解决递归 Promise

javascript - 无法使用 Node 检查器进行调试 - 出了什么问题?

javascript - Node.js Express 静态服务器卡在图像上 - 仅限 Chrome

node.js - res.redirect 不是 Promise 中的函数

javascript - 异步还是同步?我该如何处理这些API调用?

javascript - 将嵌套回调转换为 Promise

javascript - Nodejs 是否支持不同类中的同名函数?

javascript - 如何在 .then() 链中访问先前的 promise 结果?

javascript - 为什么在回调中取消 bluebird promise 会停止 setInterval?