【问题标题】:Why do both Promise's then & catch callbacks get called?为什么 Promises then 和 catch 回调都会被调用?
【发布时间】:2017-02-25 10:46:02
【问题描述】:

我有以下代码,当它执行时,它返回“rejected”和“success”:

// javascript promise
var promise = new Promise(function(resolve, reject){
  setTimeout(function(){reject()}, 1000)
});
promise
  .catch(function(){console.log('rejected')})
  .then(function(){console.log('success')});

谁能解释一下为什么会记录成功?

【问题讨论】:

  • catchtry...catch 中的作用相同。它捕捉到拒绝,而不仅仅是点击它。要达到预期的行为,您需要从 catch 返回一个被拒绝的承诺 - 或者更好的是,使用单个 then 和第二个回调。
  • 您希望promise.then(function(){console.log('success');}, function(){console.log('rejected');}) 获得其中一个,而不是两个。

标签: javascript ecmascript-6 es6-promise


【解决方案1】:

类似于@Timar,对我来说,调用 catch 的原因是“then”包含异常代码。所以在正常执行“then”之后,当它到达异常代码时,它会在“catch”xD中处理异常

【讨论】:

    【解决方案2】:

    对我来说,catch() 在一个成功的承诺之后被调用,.then() 中没有错误。

    原因是,我听到了一个随着成功的承诺而变化的值,并运行了一个方法。

    这个方法抛出了一个静默错误,因为它被算作 Promise 的一部分。

    【讨论】:

      【解决方案3】:

      对于那些成功解决的承诺和类似.then > .catch 的链,但仍然调用了thencatch这可能是因为你的then 有除非您在 catch 中明确解决该错误,否则您无法看到该错误引发的错误。这是我最讨厌的地方之一,即使在严格模式下,Promises 也会吸收错误。

      const promise = new Promise(resolve => resolve())
      .then(() => {
          console.log('then');
          not.defined = 'This causes the catch to fire even though the original promise resolved successfully.';
      })
      .catch((e) => {
          console.log('catch');
          // console.error(e);
      });
      

      【讨论】:

        【解决方案4】:

        谁能解释为什么记录成功?

        简而言之:.catch 之后的 Promise 链中的 .then 将始终被执行(除非它本身包含错误)。

        理论解释

        您的代码实际上只是一个Promise 链,它首先同步执行,然后将其设置为异步完成。 Javascript 引擎会将任何reject()Error 传递给链中的第一个.then,其中包含reject 回调。拒绝回调是传递给 .then 的第二个函数:

        .then(
        function (){
            //handle success
        },
        function () {
            //handle reject() and Error
        })
        

        .catch 的使用只是语法糖:

        .then(null, function () {
            //handle reject() or Error
        })
        

        每个.then 都会自动返回一个新的Promise,后续.then (或.catch 也是.then 的)可以对其进行操作。

        可视化承诺链的流程

        您可以通过以下示例可视化您的代码流程:

        var step1 = new Promise (function (resolve, reject) {
        
          setTimeout(reject('error in step1'), 1000);
        })
        
        var step2 = step1.then(null, function () {
        
          // do some error handling
          return 'done handling errors'
        })
        
        var step3 = step2.then(function () {
        
          // do some other stuff after error handling
          return 'done doing other stuff'
        }, null)
        
        setTimeout (function () {
        
        console.log ('step1: ', step1);
        console.log ('step2: ', step2);
        console.log ('step3: ', step3);
        
        console.log();
        console.log ('Asynchronous code completed')
        console.log();
        }, 2000);
        
        console.log ('step1: ', step1);
        console.log ('step2: ', step2);
        console.log ('step3: ', step3);
        
        console.log();
        console.log ('Synchronous code completed')
        console.log();
        

        在运行时会在控制台中产生以下输出:

        step1:  Promise { <rejected> 'error in step1' }
        step2:  Promise { <pending> }
        step3:  Promise { <pending> }
        
        Synchronous code completed
        
        step1:  Promise { <rejected> 'error in step1' }
        step2:  Promise { 'done handling errors' }
        step3:  Promise { 'done doing other stuff' }
        
        Asynchronous code completed
        

        【讨论】:

          【解决方案5】:

          then 回调被调用是因为 catch 回调在它之前,而不是之后。拒绝已由catch 处理。如果更改顺序(即 (promise.then(...).catch(...))),则不会执行 then 回调。

          MDN 表示.catch() 方法“返回一个新的承诺,解析为回调的返回值”。你的 catch 回调没有返回任何东西,所以这个 promise 用 undefined 值解决。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-06-23
            • 1970-01-01
            • 1970-01-01
            • 2019-09-28
            • 2017-03-15
            • 1970-01-01
            • 1970-01-01
            • 2020-05-10
            相关资源
            最近更新 更多