在async await中不使用try catch该如何捕捉错误呢?

290 阅读1分钟

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

这是源码共读的第21期,链接:juejin.cn/post/708310…

问题

在日常开发中,我们经常使用经常用async await来处理异步任务,如数据请求等。

  function getUser() {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve({
          id: 1,
          name: "张三"
        });
      }, 1000);
    });
  }

  async function getData() {
   try {
    let data = await getUser();
    console.log(data);
   } catch (error) {
        console.log(error);
   }
  }

  getData();

对于async函数中出现的错误我们经常使用try catch捕捉,但是当其中业务逻辑很多的时候就会出现很多try catch块,显得代码臃肿。

async function asyncTask(cb) {
    try {
       const user = await UserModel.findById(1);
       if(!user) return cb('No user found');
    } catch(e) {
        return cb('Unexpected error occurred');
    }

    try {
       const savedTask = await TaskModel({userId: user.id, name: 'Demo Task'});
    } catch(e) {
        return cb('Error occurred while saving task');
    }

    if(user.notificationsEnabled) {
        try {
            await NotificationService.sendNotification(user.id, 'Task Created');  
        } catch(e) {
            return cb('Error while sending notification');
        }
    }

    if(savedTask.assignedUser.id !== user.id) {
        try {
            await NotificationService.sendNotification(savedTask.assignedUser.id, 'Task was created for you');
        } catch(e) {
            return cb('Error while sending notification');
        }
    }

    cb(null, savedTask);
}

可选的解决方案

使用await-to-js库可使代码变得更简洁。

import to from 'await-to-js';

async function asyncTask() {
     let err, user, savedTask;

     [err, user] = await to(UserModel.findById(1));
     if(!user) throw new CustomerError('No user found');

     [err, savedTask] = await to(TaskModel({userId: user.id, name: 'Demo Task'}));
     if(err) throw new CustomError('Error occurred while saving task');

    if(user.notificationsEnabled) {
       const [err] = await to(NotificationService.sendNotification(user.id, 'Task Created'));  
       if (err) console.error('Just log the error and continue flow');
    }
}

分析源码

截屏2022-07-01 17.26.56.png 从源码中我们可以看出await-to-js对传入的promise进一步处理,通过then方法返回处理成功的promise,成功的值为[null,data]。通过catch方法返回处理失败的promise,失败的返回值为[err,undefined]。然后在对to方法使用await时,使用数组解构出返回的结果来捕捉错误,这样就省去了使用try catch块捕捉错误。

参考

blog.grossman.io/how-to-writ…

github.com/scopsy/awai…