【问题标题】:Promise control flow - catch versus onRejected [duplicate]Promise 控制流 - catch 与 onRejected [重复]
【发布时间】:2016-05-31 06:02:16
【问题描述】:

我现在想知道为什么这个 ES6 原生 Promise 设置中的 throw 没有到达 catch 块

new Promise(function(resolve,reject){

    reject('bar')

}).then(function resolved(){

    console.log('resolved 1');

}, function rejected(){

    console.log('rejected 1')
    throw new Error();

}).then(function resolved(val){

    console.log('resolved 2');

}, function rejected(){

    console.log('rejected 2');

}).catch(function(err){

    console.log('catch');

});

我正在寻找一种将控制流传递给 catch 块的方法,但是如果我使用了一个被拒绝的处理程序,如果我抛出一个错误,控制就会在那里结束,而不是在 catch 中。

简单来说,我正在寻找一种方法来结束 catch 块,即使有一个 onRejected 处理程序......有没有办法做到这一点?

new Promise(function(resolve,reject){

    throw new Error(); // this goes to onRejected
    reject('bar'); // this goes to onRejected


}).then(function onResolved(){

    console.log('resolved');

}, function onRejected(){

    console.log('rejected')


}).catch(function(err){

    console.log('catch');

});

我的目标是根据是否抛出错误与是否调用拒绝来分别分支。不确定是否可能。也许有一种方法可以显式调用 catch ? 如果可能的话,我想找到一种方法来做到这一点,而不会在最终的 onRejected 处理程序中显式抛出新错误

这是我的目标,使用 cmets:

new Promise(function(resolve,reject){

    if(success){
       resolve('success');   //this goes to next onResolved
    }
    else if(fail){
       reject('fail');      //this goes to next onRejected (or catch if there is no onRejected)
    }
    else {
       throw new Error('Fatal');  //this goes to next catch
    }

});

这就是我正在寻找的行为

【问题讨论】:

  • 当您使用拒绝处理程序“处理”拒绝时,拒绝现在被视为“已处理”并且承诺状态更改为已完成,除非您从拒绝处理程序返回被拒绝的承诺或者您从拒绝处理程序。这就是 promise 拒绝处理程序的设计方式。你无法改变这一点。如果您希望不处理拒绝并继续传播,则抛出或返回拒绝的承诺。没有办法绕过这个基本的设计决策。
  • 你无法区分“next catch”和“next onrejected”——.catch(…) 只是.then(null, …) 的糖,其行为完全相同。如果你想分支,你应该actually branch.

标签: javascript node.js promise es6-promise


【解决方案1】:

错误未到达.catch() 的原因是在onRejected 内处理错误。

将在onRejected 中处理的错误再次传递给onRejected 中的链接.catch() throw 错误

new Promise(function(resolve,reject){

    throw new Error(); // this goes to onRejected
    reject('bar'); // this goes to onRejected


}).then(function onResolved(){

    console.log('resolved');

}, function onRejected(err){

    console.log('rejected')
    throw err

}).catch(function(err){

    console.log(err, 'catch');

});

编辑、更新

要在onRejected 之前处理错误,请在链接.then() 之前添加.catch()

var success = 0,
  fail;

var p = new Promise(function(resolve, reject) {

  if (success) {
    resolve('success'); //this goes to next onResolved
  } else if (fail) {
    reject('fail'); //this goes to next onRejected (or catch if there is no onRejected)
  } else {
    throw new Error('Fatal'); //this goes to next catch
  }

});

p.catch(function(err) {
    console.log("error handled within catch:", err)
})
.then(function(data) {
    // error handled, `p` is now `resolved`
    console.log("resolved", data)
  }, function(err) {
    console.log("rejected", err)
})

【讨论】:

  • 是的,谢谢,但实际上,我想避免这种情况,因为这是一个库,我不想要求用户输入 onRejected,我想要一些流程直接去catch...有意义吗?
  • “我想让一些流程直接进入捕获” 不确定是否正确解释?
  • 也许我可以在已解决而不是在被拒绝时加入...这将是一个技巧
  • 基本上,我想分支代码-->如果流程最终在catch中,这意味着一件事(更致命的错误)然后如果流程最终被拒绝(不太致命的错误)..这是我目前的目标
  • 是的,可以在onResolved 中使用throw。但是,如果在 onRejected 之前的 .catch() 中处理错误,则错误不会到达后续的 .catch()
猜你喜欢
  • 2016-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-02
  • 2017-04-30
  • 1970-01-01
  • 1970-01-01
  • 2018-03-20
相关资源
最近更新 更多