promise中的错误捕获
接上篇文章留下的一个没有解决的问题:在promise中的错误为什么在外层函数捕获不到?
来看下面一个栗子:
var o = {};
function A(){
try{
o.show();
}catch(err){
}
}
function B(){
try{
A();
console.log("你看不见我")
}catch(err){
console.log(err)
}
}
B();//输出结果:"你看不见我"
上面的栗子说明 try/catch 在捕获到错误后阻止了错误向上传递。你只能手动抛出错误让上层函数捕获。
var o = {};
function A(){
try{
o.show();
}catch(err){
throw err
}
}
function B(){
try{
A();
console.log("你看不见我")
}catch(err){
console.log(err)
}
}
B();//输出结果:"[TypeError: Object #<Object> has no method 'show']"
再看看文章开头提到的问题 在promise中的错误为什么在外层函数捕获不到?
###真相只有一个
promise模块核心代码core.js:
...
/*直接跳至关键处*/
var cb = state ? deferred.onFulfilled : deferred.onRejected
if (cb === null) {
(state ? deferred.resolve : deferred.reject)(value)
return
}
var ret
/* #A */
try {
ret = cb(value)
}
catch (e) {
deferred.reject(e)
return
}
/* #B */
deferred.resolve(ret)
...
注意 #A 与 #B 之间的代码。没错就是它!!!这里 catch 错误后并没有将其抛出,而是传递给了下级 reject 并结束当前函数。
好了,现在菊势基本明了了。问题根源便是 Promise 始终劫持着错误对象没有抛出,导致外层函数捕获不到错误。
那么再往下看 Promise.catch 方法又是如何捕获错误的?
Promise.prototype['catch'] = function (onRejected) {
return this.then(null, onRejected);
}
原来 Promise.catch 不过是 Promise.then(null,reject) 的缩写版。
其实 Promise 作者是建议在所有 Promise 对象后加上 Promise.done 方法。Promise.catch 方法只是为了与ES6标准规范保持一致而添加的。
'use strict';
var Promise = require('./core.js')
var asap = require('asap')
module.exports = Promise
Promise.prototype.done = function (onFulfilled, onRejected) {
var self = arguments.length ? this.then.apply(this, arguments) : this
self.then(null, function (err) {
asap(function () {
throw err
})
})
}
Promise.done 的作用与 Promise.then 基本一致(注意done并没有 return Promise对象,所以 done 只能放在最后),只是在后面加了一层抛出捕获到的错误。