【若川视野 x 源码共读】第21期 | await-to-js

89 阅读2分钟

await-to-js

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

promise和async await

在es6出现之前,对于异步的操作主要通过回调函数形式实现.如jquery在数据请求上的封装

$.get(url1,() => {
    $.get(url2,() => {
        $.get(url3,() => {
            $.get(url4,() => {})
        })
    })
})

es6后引入了promise,可以让上述代码更加优雅实现,可以通过then来实现链式调用。catch来捕获错误

axios.get(url1)
.then(() => axios.get(url2))
.then(() => axios.get(url3))
.then(() => axios.get(url4))
.catch((err) => {
    console.log(err)
})

es7引入了async await来使异步代码看起来更像同步,但是async对于错误的捕获需要使用trycatch或者在await的promise后面增加catch的捕获

async function test() {
   const value1 =  await axios.get(url1)
   const value2 =  await axios.get(url2)
   const value3 =  await axios.get(url3)
   const value4 =  await axios.get(url4)
}

await-to-js

那么有什么办法可以不用每次在写async函数不写trycatch呢?

这边已经有人帮我们造好轮子了,具体用法如下

npm i await-to-js --save
import to from 'await-to-js';
// If you use CommonJS (i.e NodeJS environment), it should be:
// const to = require('await-to-js').default;

async function asyncTaskWithCb(cb) {
     let err, user, savedTask, notification;

     [ err, user ] = await to(UserModel.findById(1));
     if(!user) 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');
    }

    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');
    }

    cb(null, savedTask);
}

async function asyncFunctionWithThrow() {
  const [err, user] = await to(UserModel.findById(1));
  if (!user) throw new Error('User not found');
  
}

此函数和await连用返回一个错误信息和成功的数据。那么具体这个是怎么实现的。

源码实现

具体实现不难,通过封装了一层,把cathch和then来实现,这样在async函数中,不会因为一个错误导致整个函数中断执行

export function to(promise, errorExt) {
  return promise
    .then((data) => [null, data])
    .catch((err) => {
      if (errorExt) {
        const parseError = Object.assign({}, err, errorExt);
        return [parseError, undefined];
      }
      return [err, undefined];
    });
}

结束语

通过阅读await-to-js 这个库,学习了如何不使用trycatch来实现错误的捕获