上篇文章介绍了Promise和Async Await有什么区别(可以点击这里),Async Await是Promise的进化版,但是它的本质还是Promise,所以要想学好Async Await 必须先精通Promise!好了,废话不多说,今天接着上次没说完的话题,介绍Promise及Async Await 如何异常捕获?
一、Promise
promise(实例).then后面第二个参数可以捕获到异常。
let promise = new Promise((resolve, reject) => {
reject('错误');
});
promise.then(() => {}, (error) => {
console.log(error); //'错误'
});
promise(实例).catch也可以捕获到异常
let promise = new Promise((resolve, reject) => {
reject('错误');
});
promise.catch((error) => {
console.log(error);
});
- 两者有什么区别?我们用代码一个一个验证再下结论!
let promise = new Promise((resolve, reject) => {
reject('失败');
});
promise.then(() => {
}, (err) => {
}).catch((err) => {
console.log(err);//这里没有执行
});
--------------------------------------------
promise.then(() => {
}, (err) => {
console.log(err); //失败
}).catch((err) => {
console.log(err);//这里没有执行
});
--------------------------------------------
promise.then(() => {
}).catch((err) => {
console.log(err);//失败
}).then(() => {
}, (err) => {
console.log(err)//这里没有执行
});
结论: then 第二个参数和catch 是有优先级关系的,写在前面的先捕获,后面就没有错误可以捕获了。
let promise = new Promise((resolve, reject) => {
reject('失败');
});
promise.then(() => {
}, (err) => {
//默认执行 return Promise.resolve();
}).catch((err) => {
console.log(err); //这里没有执行
}).then(() => {
console.log('我会执行')
});
结论:为什么会有优先级关系? 因为then 第二个参数(或者第一个参数或者catch)默认返回了一个新的Fulfilled的状态的Promise,等同于return Promise.resolve(),所以后面的then会执行,而catch就不会执行了
let promise = new Promise((resolve, reject) => {
reject('失败');
});
promise.then(() => {
}, (err1) => {
return promise1;
}).then(() => {
}, (err2) => {
console.log(err2); //ReferenceError: promise1 is not defined
return promise2;
}).then(() => {
}, (err3) => {
console.log(err3); //ReferenceError: promise2 is not defined
});
------------------------------------------
promise.then(() => {
}, (err1) => {
return promise1;
}).then(() => {
}).catch((err3) => {
console.log(err3); //ReferenceError: promise1 is not defined
});
-------------------------------------------
promise.then(() => {
}, (err1) => {
}).then(() => {
return promise1;
}).catch((err3) => {
console.log(err3); //ReferenceError: promise1 is not defined
});
结论:catch 写法是针对于整个链式写法的错误而捕获的,而 then的第二个参数是针对于上一个返回的 Promise 的。所以我们平时写代码尽量用catch去捕获异常
let promise = new Promise((resolve, reject) => {
reject('失败');
});
promise.then(() => {
}, (err1) => {
return promise1;
}).then(() => {
//这里不会执行,直接跑下个then
}).then(undefined, (err3) => {
console.log(err3); //ReferenceError: promise1 is not defined
});
//等价于
promise.then(() => {
}, (err1) => {
return promise1;
}).then(undefined, (err3) => {
console.log(err3); //ReferenceError: promise1 is not defined
});
//这就是catch能捕获整个链式写法的错误,而then的第二个参数只能捕获到上一个返回的Promise的错误!
结论: catch() 方法返回一个Promise,并且处理拒绝的情况。它的行为与调用Promise.then(undefined, onRejected) 相同
//一道promise 值穿透的面试题,
Promise.resolve(1).then(2).then(console.log); //1
结论: 当then传的值不是一个函数的时候,就将值传递给下一个then,也叫做值穿透
,不懂的话可以看promise源码怎么执行的,大概是这样,判断一下callback是否是函数,如果不是函数,就将上一层的值赋值给value,相当是return Promise.resolve(value)实现了所说的值穿透,请原谅我又跑题了!下面说下Async Await!
二、Async Await
async函数返回的是一个Promise,所以我们可以在外面catch住错误。
async function test() {
await new Promise((resolve, reject) => reject('错误'));
};
test().catch((data) => console.log(data)); //错误
你不想在外面catch,你可以在函数内部可以使用try...catch语句。
async function test() {
try {
await new Promise((resolve, reject) => reject('错误'));
} catch (error) {
console.log(error); //错误
};
};
test();
await 后面跟着的肯定是一个Promise,也可以在Promise后面catch。
async function test() {
await new Promise((resolve, reject) => reject('错误')).catch((data) => console.log(data));
await new Promise((resolve, reject) => reject('错误1')).catch((data) => console.log(data));
await new Promise((resolve, reject) => reject('错误2')).catch((data) => console.log(data));
};
test(); //错误,错误1,错误2
- 可以在上面的写法基础上,我们可以优化一下,封装下提取错误函数。
let promiseValue = (promise) => {
return promise.then((data) => [null, data]).catch((err) => [err]);
};
async function test() {
[err, data] = await promiseValue(new Promise((resolve, reject) => reject('错误')));
if (err) console.log(err);
[err1, data1] = await promiseValue(new Promise((resolve, reject) => reject('错误1')));
if (err1) console.log(err1);
[err2, data2] = await promiseValue(new Promise((resolve, reject) => reject('错误2')));
if (err2) console.log(err2);
};
test();//错误,错误1,错误2