第4集丨Promise.prototype.catch

认识catch方法

Promise.prototype.catch()方法是.then(null, rejection)或.then(undefined, rejection)的别名,用于指定发生错误时的回调函数。

new Promise (function (resolve, reject) {
        //var rtn = x; 
        resolve("111")
}).then(function (result) {
        var rtn = y;//--这里的错误也会被捕获
}).catch(function (error) {
    console.log(error);
    //ReferenceError: x is not defined
    //ReferenceError: y is not defined
})
  • 上面代码中,通过构造器方法返回一个 Promise 对象,如果该对象状态变为resolved,,则会调用then()方法指定的回调函数;如果异步操作抛出错误,状态就会变为rejected,就会调用catch()方法指定的回调函数,处理这个错误。
  • 另外,then()方法指定的回调函数,如果运行中抛出错误,也会被catch()方法捕获。
p1.then(function (result) {
        var rtn = y;//--这里的错误也会被捕获
}).catch(function (error) {
    console.log(error);
    //ReferenceError: y is not defined
})

// 等同于

p1.then(function (result) {
        var rtn = y;
}).then(null, function (error) {
    console.log(error);
    //ReferenceError: y is not defined
})

案例剖析

var p1 = new Promise (function (resolve, reject) {
        throw new Error("test");  //--报错就会被catch捕获
})

p1.then(function (result) {
      console.log(result);
}).catch(function (error) {
    console.log(error);

})

  • 上面代码中,promise抛出一个错误,就被catch()方法指定的回调函数捕获。注意,上面的写法与下面两种写法是等价的。
//写法1
var p1 = new Promise (function (resolve, reject) {
        try {
            throw new Error("test")
        } catch (e) {
            reject(e)
        }
})

p1.then(function (result) {
      console.log(result);
}).catch(function (error) {
    console.log(error);

})



//写法2
var p1 = new Promise (function (resolve, reject) {
        reject(new Error("test"));
})

p1.then(function (result) {
      console.log(result);
}).catch(function (error) {
    console.log(error);

})
  • 比较上面两种写法,可以发现reject()方法的作用,等同于抛出错误。

无效错误

如果 Promise 状态已经变成resolved,再抛出错误是无效的。

var p1 = new Promise (function (resolve, reject) {
        resolve("ok")
        throw new Error("test");
})

p1.then(function (result) {
      console.log(result);  //ok
}).catch(function (error) {
    console.log(error);

})
  • 上面代码中,Promise 在resolve语句后面,再抛出错误,不会被捕获,等于没有抛出。因为 Promise 的状态一旦改变,就永久保持该状态,不会再变了。

冒泡性质

Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个catch语句捕获。

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

好的习惯

一般来说,不要在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方法执行中的错误,也更接近同步的写法(try/catch)。因此,建议总是使用catch()方法,而不使用then()方法的第二个参数。

Promise 会吃掉错误

跟传统的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 对象,内部有语法错误。浏览器运行到这一行,会打印出错误提示ReferenceError: x is not defined,但是不会退出进程、终止脚本执行,2 秒之后还是会输出123。这就是说,Promise 内部的错误不会影响到 Promise 外部的代码,通俗的说法就是“Promise 会吃掉错误”。

catch()方法的返回值也是返回一个Promise对象

一般总是建议,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()方法。

catch方法中,还能继续抛出错误

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

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

上面代码中,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()方法抛出的错误。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值