本文参加了由公众号@若川视野 发起的每周源码共读活动, 点击了解详情一起参与。
这是源码共读的第21期 | await-to-js 如何优雅的捕获 await 的错误
1. async/await的使用以及错误捕获
ES6给我们提供了Promise,Generator,async/await处理异步请求的api,async/await同步的方法执行异步操作。
async function test(){
const res =await fetch('xxx')
}
//如有多个请求,从最开始的回调地狱,到promise.then链式调用
//async/await 提供了新的范式
async function send(){
const res1 =await requset1()
const res2 = await requset2(res1)
}
//错误捕获一般使用try...catch
async function test(){
let res =null
try{
res = await Promise.reject('1')
try{
res = await Promise.reject('12')
} catch(error){
console.log(error)
}
} catch(error){
console.log(error)
}
}
//promise.catch()
Promise.resolve(1).then(()=>{
Promise.reject(2)
}).catch(err=>{
console.log(err)
})
2. await-to-js插件使用及原理
2.1 使用:
asycn function testTo(){
const [error,data] = await to(getuser)
//没有错误则error为null,data为undefined
if(error){
console.log(error)
}
if(data){
console.log(data)
}
}
2.2 await-to-js源码
/**
* @param { Promise } promise
* @param { Object= } errorExt - Additional Information you can pass to the err object
* @return { Promise }
*/
/**可以传递两个参数,一个异步请求方法和额外的错误提示信息
返回一个数组[error,data],
* 请求成功: error=null,data为api的返回数据
* 请求失败:使用promise的catch来捕获错误,data=undefined;err为错误信息,若有额外的错误信息传递进来会合并
*/
export function to<T, U = Error> (
promise: Promise<T>,
errorExt?: object
): Promise<[U, undefined] | [null, T]> {
return promise
.then<[null, T]>((data: T) => [null, data])
.catch<[U, undefined]>((err: U) => {
if (errorExt) {
const parsedError = Object.assign({}, err, errorExt);
return [parsedError, undefined];
}
return [err, undefined];
});
}
export default to;
3. 扩展 async/await原理
async/await本身是generater的语法糖,下面模拟下它的实现
function co(callback){
return new Promise((resolve,reject)=>{
function step(data){
const {value,done} = callback.next(data)
if(!done){
Promise.resolve(value).then((data)=>{
step(data)
}).catch(error=>reject(error))
}else{
resolve(data)
}
}
step()
})
}
function* read(){
yield 2;
yield 3
}
co(read())
小结
- await-to-js给我们提供了另外一种捕获错误的思路,这种类似react的hook用法,
const [count, setCount] = useState(0)
- 这里推荐react的一个请求插件[ React Query 中文文档](概览 | React Query 中文文档 (cangsdarm.github.io))是类似的范式。
const { isLoading, error, data } = useQuery("repoData", () =>
fetch("https://api.github.com/repos/tannerlinsley/react-query").then(
(res) => res.json(),
),
);
if (isLoading) return "Loading...";
if (error) return "An error has occurred: " + error.message;