我正在使用以下可正常工作的代码,但问题是当我收到错误时,我希望它能阻止所有其他的承诺 . 例如,如果 chi.getCommand(val1, val2)
,将发送拒绝,我得到异常捕获,我想取消 chss.exe
和 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: here! ,以便调用解析!
UPDATE1
唯一阻止getStatus的是当我把 process.exit(1)
但是这个杀了所有进程,我只是想停止函数getCommand的所有链,以防Im arriving to the catch block ,
有办法吗?它是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);
});
我得到的错误是
{[错误:生成cmdr ENOENT]代码:'ENOENT',错误:'ENOENT',系统调用:'spawn cmdbug',路径:'cmdr',spawnargs:['/ g','npm install express --save' ] {{错误:生成cmdbug ENOENT]代码:'ENOENT',错误:'ENOENT',系统调用:'spawn cmdbug',路径:'cmdr',spawnargs:['/ g','npm install express --save ']}子进程失败,代码为-4058
仍然是getStatus的进程正在写入控制台 .
我使用而不是用于测试的代码是:
getCommand 是抛出 error! 的函数
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;
})
}();
The code for check status is:
// 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 当尝试更改As @artur建议在第二个选项中我在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);
}
}
});
});
}
2 回答
正如@Esailija所指出的那样
bluebird
内置了取消机制 - 这对于简单的异步计算非常好并且肯定是 totally fine .更新
您可以取消递归定义的操作(例如重试) . 在这种情况下,最好的策略不是通过递归行为来破坏动作本身 . 在下面的代码片段中,我创建了一个非常简单的包装器,它说明了我的观点 .
原始答案
一般来说承诺很好,但他们不提供开箱即用的取消机制 . 在某些情况下(例如https://github.com/whatwg/fetch/issues/27)这是非常有问题的,在您的情况下,取消选项也非常方便 . 唯一有效的选择是自己添加它 .
基于承诺的基本解决方案
我将问题提炼到最低限度并使浏览器可以运行 . 以下方法的缺点是取消后,承诺永远不会
resolve
也不会reject
- 这在一般情况下肯定是unacceptable . 或者.cancel
可以用某些特殊符号拒绝承诺 . 这些方法似乎都不优雅 .基于可观察的解决方案
对于基本的操作顺序,承诺是好的,但有一种方法可用更优越的方法:即可观察的 . 它们不仅提供内置的取消/处理机制,而且允许处理多个发出的值,并在非常严格的控制下保持复杂的异步执行 .
好吧,在您的实际代码(UPDATE1中的代码)中,您同时运行
getCommand
到getStatus
,而不是按顺序运行 . 你在子进程失败之前调用(启动)它们,并且当它发生时,没有什么可以阻止getStatus
.只需将它们链接在一起就像在你的第一个片段中那样,
getCommand
中的拒绝将导致getStatus
根本不运行 . 您可以使用