Promise被拒绝后停止正在运行的进程

我使用下面的代码工作正常,但问题是,当我得到一个错误,我希望它停止所有其他的承诺。 例如,如果chi.getCommand(val1, val2)将发送一个拒绝,我得到了exception捕获,我想取消对chss.exeapp.getStatus(12);的承诺app.getStatus(12); 我怎样才能做到这一点?

  var start = Promise.all([ chi.getCommand(val1, val2), chi.findAndUpdateCustomer() ]).spread(function (command, customer) { return chss.exe(runnableDoc, command, customer) .delay(10) .then(function (val) { if (val) console.log(val); return app.getStatus(12); }); }).catch(function (err) { // catch and handle errors and when it come to here I want it to stops all the chain above }); 

这是get命令的代码简而言之:

 function getCommand(method, cmd) { return new Promise(function (resolve, reject) { ... child.stderr.on('data', function (data) { console.log('stderr: here!' + data); reject(data); }); } 

控制台日志stderr:在这里! 被打印,所以决心被称为!

UPDATE1

唯一停止getStatus的是当我把process.exit(1)但是这个杀死所有的进程,我只是想停止所有的函数getCommand的链,以防万一到达catch块

  1. 有没有办法?
  2. 是blueBird中的错误吗? 我用“蓝鸟”:“2.9.34”

function getCommand(method,cmd){return new Promise(function(resolve,reject){

 var spawn = require('child_process').spawn; var ls = spawn("cmdbug",["/c","npm install express --save"]); ls.on('error', function (err) { console.log(err); reject(err); }); 

我得到的错误是

{[Error:spawn cmdr ENOENT] code:'ENOENT',errno:'ENOENT',syscall:'spawn cmdbug',path:'cmdr',spawnargs:['/ g','npm install express –save'] } {{error:spawn cmdbug ENOENT] code:'ENOENT',errno:'ENOENT',syscall:'spawn cmdbug',path:'cmdr',spawnargs:['/ g','npm install express –save' ]}代码为-4058的subprocess失败

仍然getStatus的过程正在写入控制台。

我使用而不是testing的代码是:

getCommand是抛出错误的函数

 var start= function () { return new Promise.all([ childP.getChildProcessCommand(val1, val2), childP.findAndUpdateCustomer() ]).spread(function (cmd, updated) { //Execute child process return Promise.all([ childP.getCommand('spawn', cmd), app.getStatus(51000,10,1); ]).catch(function (err) { // catch and handle errors console.log("An error occur: " + err); return; }) }).catch(function (err) { // catch and handle errors console.log("An error occur: " + err); return; }) }(); 

检查状态的代码是:

 // Returns a promise that resolves when the port is open checkPortStatus: function(port, host){ return new Promise((resolve, reject) => { portscanner.checkPortStatus(port, host, function(error, status) { if(error) reject(error); else if(status === 'open') resolve(status); else reject(new Error('Port is not open')); }); }); }, // THE API function getStatus: function(port, retriesLeft) { const TIME_BETWEEN_CHECKS = 1000; const HOST = '127.0.0.1'; const RETRIES = 20; retriesLeft = retriesLeft === void 0 ? RETRIES : retriesLeft; if(!port) throw new Error('Port is required'); if(retriesLeft === 0) Promise.reject('Timed Out'); return new Promise((resolve, reject) => { // If it rejects, we do added work. this.checkPortStatus(port, host).then(resolve, error => { console.log("Waiting for port " + port + " attempt: " + retry); setTimeout(() => { this.getStatus(port, retriesLeft - 1).then(resolve, reject); }, TIME_BETWEEN_CHECKS); }); }); } 

我看到控制台中的错误,仍然看到10次以下的控制台日志。 console.log(“等待端口”+端口+“尝试:”+重试);

UPDATE2当试图改变第二个选项中的@Aururbuild议我收到错误的recoursive调用错误是:

TypeError:无法读取未定义的属性'then'

这是我试过的:

 getStatus: function(port, retriesLeft) { const TIME_BETWEEN_CHECKS = 1000; const HOST = '127.0.0.1'; const RETRIES = 20; retriesLeft = retriesLeft === void 0 ? RETRIES : retriesLeft; if(!port) throw new Error('Port is required'); if(retriesLeft === 0) Promise.reject('Timed Out'); var promise = new Promise((resolve, reject) => { // If it rejects, we do added work. this.checkPortStatus(port, host).then(resolve, error => { console.log("Waiting for port " + port + " attempt: " + retry); setTimeout(() => { //The error in the following recursive call this.getStatus(port, retriesLeft - 1).then(resolve, reject); }, TIME_BETWEEN_CHECKS); }).catch(function (error) { return reject(error); }); return { promise:promise, cancel: function() { console.log('cancelling'); clearTimeout(token); } } }); }); } 

正如@Esailija指出, bluebird内置了取消机制 – 这对于简单的asynchronous计算来说确实很不错。

 Promise.config({ cancellation: true }); function createCancellableMock(result, time) { return new Promise(function(resolve, reject, onCancel) { // var child = runCommand(); var token = setTimeout(function() { if (result) { console.log('almost done', result); resolve(result); } else { reject('_ERR_'); } }, time); onCancel(function() { console.log('cancelling'); // child.kill('SIGTERM'); clearTimeout(token); }) }) } var op1 = createCancellableMock('ok-1', 1000); //var op2 = createCancellableMock('ok-2', 500); var op2 = createCancellableMock(null, 500); // will be rejected Promise.all([op1, op2]) .spread(function(v1, v2) { console.log('BOTH-OK', v1, v2) }) .catch(function() { console.error('ERROR'); op1.cancel(); }) .finally(function() { console.log('finally'); }) 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.3.0/bluebird.core.js"></script> 

那么,在你的实际代码(来自UPDATE1的代码)中,你正在同时运行getCommandgetStatus ,而不是按顺序。 你在subprocess失败之前调用(启动)他们两个,并且什么也没有停止getStatus

只要将它们链接在一起,就像在第一个代码片段中那样, getCommand中的拒绝将导致getStatus根本不运行。 您可以使用

 childP.getCommand('spawn', cmd) .timeout(5000) .then(function(cmdresult) { return app.getStatus(51000, 10, 1); }).catch(function (err) { console.log("An error occured: " + err); });