promise实例的catch方法

Promise.prototype.catch()

Promise.prototype.catch()方法是用于指定发生错误时的回调函数

getJSON('/posts.json').then(function(posts) {
  // ...
}).catch(function(error) {
  // 处理 getJSON 和 前一个回调函数运行时发生的错误
  console.log('发生错误!', error);
});

      上边代码中,getJSON( )方法返回一个Promise对象,如果该对象状态为resolved,则会调用then()方法指定的回调函数;如果异步操作抛出错误,状态就会变为rejected,就会调用catch( )方法指定的回调函数,处理这个错误。另外,then( )方法指定的回调函数,如果运行中抛出错误,也会被catch( )方法捕获。

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));

 

下面是一个例子

const promise = new Promise(function(resolve, reject) {
  throw new Error('test');
});
promise.catch(function(error) {
  console.log(error);
});
// Error: test

       上边代码中,promise抛出一个错误,就被catch方法指定的回调函数捕获。

 

Promise对象的错误具有冒泡的性质,会一直向后传递,直到被捕获为止。

getJSON('/post/1.json').then(function(post) {
  return getJSON(post.commentURL);
}).then(function(comments) {
  // some code
}).catch(function(error) {
  // 处理前面三个Promise产生的错误
});

         上边的代码中,一共有三个Promise对象:一个由getJSON( )产生,两个由then( )产生。它们中,任何一个抛出错误,都会被最后一个catch( )捕获。

 

一般来说,不在then()方法里面定义Reject状态的回调函数(即then的第二个参数),总是使用catch方法。

// bad
promise
  .then(function(data) {
    // success
  }, function(err) {
    // error
  });

// good
promise
  .then(function(data) { //cb
    // success
  })
  .catch(function(err) {
    // error
  });

         上边的代码,第二种写法优于第一种,理由是第二种写法可以捕获前面then方法执行中的错误。因此,建议总是使用catch()方法,而不是使用then( )方法的第二个参数。

 

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

const someAsyncThing = function() {
  return new Promise(function(resolve, reject) {
    // 下面一行会报错,因为x没有声明
    resolve(x + 2);
  });
};

someAsyncThing().then(function() {
  console.log('everything is great');
});

setTimeout(() => { console.log(123) }, 2000);
// Uncaught (in promise) ReferenceError: x is not defined
// 123

      上边的代码中,someAsyncThing( )函数产生的Promise对象,内部有语法错误,浏览器运行到这一行,会打印出错误提示,但是不会退出进程,终止脚本运行,2s之后还是会输出123。 这就是说,Promise内部的错误不会影响到Promise外部的代码,通俗的说法就是“Promise 会吃掉错误

 

这个脚本放在服务器执行,退出码是0(即表示执行成功)。不过,Node.js有一个unhandleRejection事件,专门监听未捕获的reject错误,上边的脚本会触发这个事件的监听函数,可以在监听函数里面抛出错误。

process.on('unhandledRejection', function (err, p) {
  throw err;
});

      上边的代码中,unhandleRejection事件的监听函数有两个参数,第一个是错误对象,第二个是报错的Promise实例,它可以用来了解发生错误的环境信息。

 

注意,Node 有计划在未来废除unhandleRejection事件。如果Promise内部有未捕获的错误,会终止进程,并且进程的退出码不为0.

 

一般总是建议,Promise对象后面要跟catch方法,这样可以处理Promise内部发生的错误。catch( )方法返回的还是一个Promise对象,因此后面还可以接着调用then()方法。

const someAsyncThing = function() {
  return new Promise(function(resolve, reject) {
    // 下面一行会报错,因为x没有声明
    resolve(x + 2);
  });
};

someAsyncThing()
.catch(function(error) {
  console.log('oh no', error);
})
.then(function() {
  console.log('carry on');
});
// oh no [ReferenceError: x is not defined]
// carry on

     上边的代码运行完catch( )方法指定的回调函数,会接着运行后面那个then()方法指定的回调函数,如果没有报错,则会跳过catch( )方法 

如下:

Promise.resolve()
.catch(function(error) {
  console.log('oh no', error);
})
.then(function() {
  console.log('carry on');
});
// carry on

      上面的代码因为没有报错,跳过了catch()方法,直接执行后面的then()方法。此时,要是then()方法里面报错,就与前面的catch()无关了。

 

catch()方法之中,还能再抛出错误

someAsyncThing().then(function() {
  return someOtherAsyncThing();
}).catch(function(error) {
  console.log('oh no', error);
  // 下面一行会报错,因为y没有声明
  y + 2;
}).catch(function(error) {
  console.log('carry on', error);
});
// oh no [ReferenceError: x is not defined]
// carry on [ReferenceError: y is not defined]

      上面代码中,第二个catch()方法用来捕获前一个catch()方法抛出的错误

 

posted on 2021-01-20 11:38  zhishiyv  阅读(979)  评论(0编辑  收藏  举报

导航