描述:

  1. 关于catch方法MDN的描述是这样的:

Internally calls Promise.prototype.then on the object upon which is called, passing the parameters undefined and the onRejected handler received; then returns the value of that call (which is a Promise )。这里说到 :

  • .catch方法在内部也是调用的Promise.prototype.then方法中的reject状态下的方法,也就是calling
    obj.catch(onRejected)内部calls obj.then(undefined, onRejected)

  • 它返回了一个失败的promise
    以及返回一个参数作为一个失败理由。值得注意的是这里返回的是一个已定型的promise,这个过程是promisependingreject的改变过程。

    p.then((val) => console.log('fulfilled:', val))
      .catch((err) => console.log('rejected', err));
    
    // 等同于
    p.then((val) => console.log('fulfilled:', val))
      .then(null, (err) => console.log("rejected:", err));
    
    
  1. 如果 Promise 状态已经变成resolved,再抛出错误是无效的。

    const promise = new Promise(function(resolve, reject) {
      resolve('ok');
      throw new Error('test');  //会被忽略,不会被捕获,等于没有抛出
    });
    promise
      .then(function(value) { console.log(value) })
      .catch(function(error) { console.log(error) });
    // ok
    

这里很好理解,就是catch是从pendingreject的状态改变,但是一个promise一旦resolve以后,状态就凝固了,无法再发生变化,因此会被忽略。

错误捕获

1. try...catch捕获错误

先来看看try...catch 语句的错误捕获机制:当多层嵌套try...catch出现时,内部的错误抛出会被最近一个catch ,直到最外层。当错误被内部的catch捕获后,就失效了。

  try {
          try {
            throw new Error("oops");
          }
          catch (ex) {
            console.error("inner", ex.message);  //catch try抛出的 错误
          }
          finally {
            console.log("finally");
          }
        }
        catch (ex) {
          console.error("outer", ex.message);  //这里的代码不执行
        }
        
        // Output:
        // "inner" "oops"
        // "finally"

再次抛出错误

 try {
          try {
         throw new Error("oops");
          }
       catch (ex) {
            console.error("inner", ex.message);
            throw ex; //这里已经捕获到了异常,这个异常就失效了;如果这里不重新throw ex,外面的catch感知不到这里的异常的,即外层的catch{}不会执行
          }
          finally {
            console.log("finally");
          }
        }
        catch (ex) {
          console.error("outer", ex.message);    //捕获 throw ex; 
        }
        
        // Output:
        // "inner" "oops"
        // "finally"
        // "outer" "oops"

2. promise捕获错误

promise 错误捕获和try...catch一样会冒泡到外层。

promise的错误抛出后会一直传递到最外层,直到被捕获;当catch捕获错误以后,返回的还是一个promise对象,可以继续链式调用。

   const p1 = new Promise((resolve, reject) => {
           setTimeout(() => resolve('成功'), 3000)
         })
     
         const p2 = new Promise((resolve, reject) => {
           setTimeout(() => reject(new Error('失败了')), 3000)
         })
     
         p1.then(function (post) {
           return p2
         })
           .then((resolve) => {
             //这里的代码不会执行
             console.log('p2 reject 第二个then执行了')
             return `第二个then的返回值`   
           })
           .catch((e) => {
             console.log(e, '=====first error')
           })
           .then((resolve) => {
             console.log('第三个then执行了,接收到的返回值为:', resolve)
           })
           .catch((e) => console.log(e, '=====error'))
     
     // Error: 失败了 at eval (test.js?33a7:92) "=====first error"
     // console.log('第三个then执行了,接收到的返回值为:', resolve)

如果.then()方法后面没有catch方法,后面紧跟着的链式调用的.then()不会执行。

     p1.then(function (post) {
          return p2
        })
          .then((resolve) => {
            //这里的代码不会执行
            console.log('p2 reject 第二个then执行了')
            return `第二个then的返回值`   
          })
          .then((resolve) => {
            //这里的代码不会执行
            console.log('第三个then执行了,接收到的返回值为:', resolve)  
          })
          .catch((e) => console.log(e, '=====error'))
    
    // Error: 失败了 at eval (test.js?33a7:92) "=====error"

3. 区别:

prmise跟传统的try/catch代码块不同的是,如果没有使用catch()方法指定错误处理的回调函数,Promise 对象抛出的错误不会传递到外层代码,即不会有任何反应。

try {
  try {
    throw new Error("oops");
  } catch (ex) {
    // console.error('inner', ex.message)
    // throw ex 
  } finally {
    console.log("finally");
  }
} catch (ex) {
  console.error("outer", ex.message); // 捕获 throw ex;
}
// finally

上面的代码,catch代码块捕获了错误,但是进行错误处理,浏览器也不会自动抛出错误,会跳过这段错误。

但如果是promise则会传递未捕获的错误,浏览器会自动抛错。

p1.then(function (post) {
  return p2
})
  .then((resolve) => {
    console.log('p2 reject 第二个then执行了')
    return `第二个then的返回值`
  })
// Uncaught (in promise) Error: 失败了
//    at eval (test.js?33a7:92)
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐