Promise被拒绝后停止正在运行的进程
我使用下面的代码工作正常,但问题是,当我得到一个错误,我希望它停止所有其他的承诺。 例如,如果chi.getCommand(val1, val2)
将发送一个拒绝,我得到了exception捕获,我想取消对chss.exe
和app.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块 ,
- 有没有办法?
- 是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的代码)中,你正在同时运行getCommand
到getStatus
,而不是按顺序。 你在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); });