【若川视野 x 源码共读】第21期 | await-to-js 如何优雅的捕获 await 的错误

193 阅读3分钟

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

前言

按部就班,一步步来。

目标

下个项目熟练使用,减少错误处理代码。

开始

安装

  • 空文件夹 test-await-to-js
  • Ctrl + Shift + ` ,选择 test-await-to-js
  • type npm i await-to-js --save
npm i await-to-js --save

文档

node_modules/await-to-js/dist/docs/index.html

Node 版本

if( Node 7.6 (or later) || an ES7 transpiler) can use.
Babel or ts for it.

  • node version >= 7.6 ? Yes.
node -v
v14.5.0

用法

/**
 * @param { Promise } promise
 * @param { Object= } errorExt - Additional Information you can pass to the err object
 * @return { Promise }
 */
function to(promise, errorExt) {
  return promise
    .then(function (data) {
      return [null, data];
    })
    .catch(function (err) {
      if (errorExt) {
        Object.assign(err, errorExt);
      }
      return [err, undefined];
    });
}

const UserModel = {
  findById: (userId) => {
    return new Promise((resolve, reject) => {
      if (userId) {
        const userObjet = {
          id: userId,
          notificationsEnabled: true,
        };

        return resolve(userObjet);
      }

      reject("Data is missing");
    });
  },
}; // 用户模块:根据id查询用户,用户存在则创建用户对象并启用通报服务,用户不存在则提示数据缺失。

const TaskModel = function ({ userId, name }) {
  return new Promise((resolve, reject) => {
    if (userId && name) {
      const newTask = {
        assignedUser: {
          id: userId,
        },
      };

      return resolve(newTask);
    }

    reject("Data is missing");
  });
}; // 任务模块: 用户id和任务名都存在则新建任务并标记此任务分配给此用户,否则提示数据缺失。

const NotificationService = {
  sendNotification: (userId, name) => {
    return new Promise((resolve, reject) => {
      if (userId && name) return resolve("Success");

      reject("Data is missing");
    });
  },
}; // 通报服务:发送通知,执行成功,用户id和任务名都存在,则发送成功。

async function asyncTask(userId, cb) {
  let err, user, savedTask, notification;
  [err, user] = await to(UserModel.findById(userId));
  if (!(user && user.id)) return cb("No user found"); // 异步任务之一:用户模块-查询用户

  [err, savedTask] = await to(
    TaskModel({ userId: user.id, name: "Demo Task" })
  );
  if (err) return cb("Error occurred while saving task"); // 异步任务之二:任务模块-给用户分配任务,并返回新任务

  if (user.notificationsEnabled) {
    [err] = await to(
      NotificationService.sendNotification(user.id, "Task Created")
    );
    if (err) return cb("Error while sending notification");
  } // 异步任务之三:通报服务-发送通报,若用户通报功能启用,则执行此任务;用户id和任务名称都存在则发送成功,否则提示错误发生在通报发送过程中。

  if (savedTask.assignedUser.id !== user.id) {
    [err, notification] = await to(
      NotificationService.sendNotification(
        savedTask.assignedUser.id,
        "Task was created for you"
      )
    );
    if (err) return cb("Error while sending notification");
  } // 若用户id和任务被分配的用户id不一致,则重新执行异步任务之三:通报服务-发送通报。

  cb(null, savedTask); //回调-新任务
}

asyncTask(1, (err, newTask) => {
  console.log("new task created");
  console.log(err);
  console.log(newTask);
});

asyncTask(null, (err, newTask) => {
  console.log("fail");
  console.log(err);
  console.log(newTask);
});

我的错误处理之路

第一阶段(使用 then 函数 catch 函数)

    funcDemo().then((res)=>{
      ...
    }).catch(err){
      ...
    }

第二阶段(使用 async/await try...catch)

    async function funcDemo(){
      try {
        await funcDemo()
        ...
      }catch(err){
        ...
      }
    }

第三阶段(使用 async/await try...throw...catch)

    async function funcDemo(){
      try {
        let res = await funcDemo()
        if(...){
        }else{
          throw res
        }
      }catch(err){
      }
    }

第四阶段(使用 await-to-js)

    async function funcDemo(){
      let err,res
      ;[err,res] = await to(funcDemo())
      ...
    }
  • 以及今天使用 await-to-js 解决了过去产生的不易于理解维护的回调地狱的代码。
  • 更接近作者的写法一步。
  • 向未来前进了一步。
  async function funcDemo(args,cb){
    let err,res,res2
    ;[err,res] = await to(funcDemo())
    ...
    ;[err,res2]= await to(funcDemo2())
    ...
  }

最后

  • 感谢源码共读活动。

    解决了工作中的不少问题,帮助我进步,感谢川哥,感谢无私奉献的人。

  • 注重实践。

    将学到的运用到工作中去。

参考链接

【若川视野 x 源码共读】第 21 期 | await-to-js 如何优雅的捕获 await 的错误

await-to-js 库

How to write async await without try-catch blocks in Javascript 官方文章