await-to-js 如何优雅的捕获 await 的错误

263 阅读2分钟

本文参加了由公众号@若川视野 发起的每周源码共读活动,    点击了解详情一起参与。

这是源码共读的第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())

小结

  1. await-to-js给我们提供了另外一种捕获错误的思路,这种类似react的hook用法,
const [count, setCount] = useState(0)
  1. 这里推荐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;