async await 的错误处理

发布于 2022-09-11 16:38:29 字数 3617 浏览 224 评论 0


async await 从语法层面给人一种非常直观的方式,可以让我们避免 callback hell 与 Promise hell 。

async function getUserInfo() {
	const id = await request.getCurrentId()
	const info = await request.getUserInfo(id)

 	return info
}

但是每一步 await 的都可能出错,为了捕获这些错误,我们使用 try...catch...

async function getUserInfo (cb) {
  try {
     const id = await request.getCurrentId()
  } catch(e) {
     return cb('an error in getCurrentId')
  }
  
  try {
    const info = await request.getUserInfo(id)
  } catch(e) {
    return cb('an error in getUserInfo')
  }

  return cb(null, info)
}

这样写一眼看上去代码异常丑陋而且不直观,国外大神 Dima 在他的文章 how-to-write-async-await-without-try-catch-blocks-in-javascript 中提到了一种解决方案,因为 await 实际上等待的是一个 Promise,因此可以使用一个函数包装一个来符合 error first 的原则,从而避免 try...catch...

function to (promise) {
  return promise.then(data => {
      return [null, data]
  }).catch(err => [err])

}

通过这个函数包装一下上面的例子

async function getUserInfo () {
  let err, id, info; 
  [err, id] = await to(request.getCurrentId())
  if(err) return console.error(err)
  
  [err, info] = await to(request.getUserInfo(id))
  if(err) return console.error(err)

  return info
}

基于这种思路,可以想到直接在每一步 await 的时候都单独 catch, 最后在最外层捕获 error

async function getUserInfo() {
  try {
    const id = await request.getCurrentId().catch(err => Promise.reject('an error in getCurrentId'))
    const info = await request.getUserInfo(id).catch(err => Promise.reject('an error in getUserInfo'))
  } catch(err) {
    errorHandle(err)
  }
}

在实际编码中,我们当然想要一个公共的 error 处理函数,不过如果你的业务太复杂了,偶尔中途需要有额外的处理逻辑也没关系,别忘了 Promise.reject() 啥都可以作为参数:

async function getUserInfo() {
  try {
    const id = await request.getCurrentId().catch(err => Promise.reject('an error in getCurrentId'))
    const info = await request.getUserInfo(id).catch(err => Promise.reject(() => {
    doSomething()
    anotherErrorHandler()
})
  } catch(err) {
    if (typeof err === 'function') err()
    else errorHandle(err)
  }
}

Dima 的处理方式已经很不错了,市面上有非常多的基于这种思想的库,可以在 npm 上 搜索,如果简单拓展下自定义 error 的信息(如code,msg),是否采用 errorFirst 的惯例,如下:

function to (promise, errorProps = {}, errorFirst = true) {
	return promise.then((data) => errorFirst ? [null, data] : [data, null])
			  .catch(err => {
				  if(errorProps) Object.assign(err, errorProps)
				  errorFirst ? [err, undefined] : [undefined, err]
			  })
  }

大概关于 async await 的错误处理就总结如上了,以后遇到更好地处理方式再说。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

回心转意

暂无简介

0 文章
0 评论
23 人气
更多

推荐作者

末蓝

文章 0 评论 0

年少掌心

文章 0 评论 0

党海生

文章 0 评论 0

飞翔的企鹅

文章 0 评论 0

鹿港小镇

文章 0 评论 0

wookoon

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文