- 本文参加了由公众号@若川视野 发起的每周源码共读活动, 点击了解详情一起参与。
- 这是源码共读的第21期,链接:【若川视野 x 源码共读】第21期 | await-to-js 如何优雅的捕获 await 的错误。
async/await
ES7推出的async/await用法,解决了早期异步解决方案回调函数的回调地狱问题。以同步的方式写异步的写法也比promise的链式调用写法更加符合编码逻辑习惯。
async/await其实是Generator 函数 + yield 的语法糖,在平时的业务代码工作中,我都是习惯用async/await处理异步请求,在每一个async函数里面都要把await的操作包裹在tryCatch中用于捕获错误,有时候可能都会忘记写tryCatch。
如果不使用tryCatch,异步操作中如果是reject或者是抛出错误,都会导致async函数执行中断,不会继续执行;await只会接收到异步操作成功的结果,不会拿到报错信息;由于以上两个问题,捕获错误很有必要。
如果不做错误处理:
任何一个
await语句后面的 Promise 对象变为reject状态,那么整个async函数都会中断执行。
async function f() {
await Promise.reject('出错了');
await Promise.resolve('hello world'); // 不会执行
}
错误处理方式
// 1、放在tryCatch中
async function myFunction() {
try {
await somethingThatReturnsAPromise();
} catch (err) {
console.log(err);
}
}
// 2、给await后面的promise添加catch错误捕获
async function myFunction() {
await somethingThatReturnsAPromise()
.catch(function (err) {
console.log(err);
});
}
以上的错误处理方式如果写多了会有点繁琐,await-to.js库通过对异步操作的结果做一个封装,能解决经常需要写tryCatch的繁琐。
await-to.js使用
const asyFn = async () => {
// fetchApi()是一个异步请求
const [error, res] = await to(fetchApi(), {
err: 'Task was created for you'
})
console.log(error, res);
}
源码解析
/**
* @param { Promise } promise
* @param { Object= } errorExt - Additional Information you can pass to the err object
* @return { Promise }
*/
export function to(promise, errorExt) {
return promise
.then(function (data) { return [null, data]; })
.catch(function (err) {
if (errorExt) {
var parsedError = Object.assign({}, err, errorExt);
return [parsedError, undefined];
}
return [err, undefined];
});
}
export default to;
向外暴露一个to方法,方法接受两个参数,第一个参数是异步操作的promise,第二个参数是自定义的错误对象。 方法的返回值是一个长度为2的数组,第一个的值是错误对象,第二个的值是异步请求成功的数据。
通过对第一个参数promise的catch错误捕获,拿到异步请求的错误信息,与第二个参数中的错误对象做一个合并且作为数组的第一个值返回,使用者可以在await的返回值中同时拿到成功和错误数据。不用再多次书写tryCatch。