async/await优雅的错误处理方法总结


Posted in Javascript onJanuary 30, 2019

前言

node.js的世界,从callback开始,不会止于async.

本文将给大家详细介绍关于async/await优雅的错误处理的相关内容,下面话不多说了,来一起看看详细的介绍吧

async/await优雅的错误处理

一般情况下 async/await 在错误处理方面,主要使用 try/catch,像这样

const fetchData = () => {
 return new Promise((resolve, reject) => {
  setTimeout(() => {
   resolve('fetch data is me')
  }, 1000)
 })
}

(async () => {
 try {
  const data = await fetchData()
  console.log('data is ->', data)
 } catch(err) {
  console.log('err is ->', err)
 }
})()

这么看,感觉倒是没什么问题,如果是这样呢?有多个异步操作,需要对每个异步返回的 error 错误状态进行不同的处理,以下是示例代码

const fetchDataA = () => {
 return new Promise((resolve, reject) => {
  setTimeout(() => {
   resolve('fetch data is A')
  }, 1000)
 })
}

const fetchDataB = () => {
 return new Promise((resolve, reject) => {
  setTimeout(() => {
   resolve('fetch data is B')
  }, 1000)
 })
}

const fetchDataC = () => {
 return new Promise((resolve, reject) => {
  setTimeout(() => {
   resolve('fetch data is C')
  }, 1000)
 })
}

(async () => {
 try {
  const dataA = await fetchDataA()
  console.log('dataA is ->', dataA)
 } catch(err) {
  console.log('err is ->', err)
 }

 try {
  const dataB = await fetchDataB()
  console.log('dataB is ->', dataB)
 } catch(err) {
  console.log('err is ->', err)
 }

 try {
  const dataC = await fetchDataC()
  console.log('dataC is ->', dataC)
 } catch(err) {
  console.log('err is ->', err)
 }
})()

这样写代码里充斥着 try/catch,有代码洁癖的你能忍受的了吗?这时可能会想到只用一个 try/catch。

// ... 这里 fetch 函数省略

(async () => {
 try {
  const dataA = await fetchDataA()
  console.log('dataA is ->', dataA)
  const dataB = await fetchDataB()
  console.log('dataB is ->', dataB)
  const dataC = await fetchDataC()
  console.log('dataC is ->', dataC)
 } catch(err) {
  console.log('err is ->', err)
  // 难道要定义 err 类型,然后判断吗??
  /**
   * if (err.type === 'dataA') {
   * console.log('dataA err is', err)
   * }
   * ......
   * */
 }
})()

如果是这样写只会增加编码的复杂度,而且要多写代码,这个时候就应该想想怎么优雅的解决,async/await 本质就是 promise 的语法糖,既然是 promise 那么就可以使用 then 函数了

(async () => {
 const fetchData = () => {
  return new Promise((resolve, reject) => {
   setTimeout(() => {
    resolve('fetch data is me')
   }, 1000)
  })
 }

 const data = await fetchData().then(data => data ).catch(err => err)
 console.log(data)
})()

在上面写法中,如果 fetchData 返回 resolve 正确结果时,data 是我们要的结果,如果是 reject 了,发生错误了,那么 data 是错误结果,这显然是行不通的,再对其完善。

(async () => {
 const fetchData = () => {
  return new Promise((resolve, reject) => {
   setTimeout(() => {
    resolve('fetch data is me')
   }, 1000)
  })
 }

 const [err, data] = await fetchData().then(data => [null, data] ).catch(err => [err, null])
 console.log('err', err)
 console.log('data', data)
 // err null
 // data fetch data is me
})()

这样是不是好很多了呢,但是问题又来了,不能每个 await 都写这么长,写着也不方便也不优雅,再优化一下

(async () => {
 const fetchData = () => {
  return new Promise((resolve, reject) => {
   setTimeout(() => {
    resolve('fetch data is me')
   }, 1000)
  })
 }

 // 抽离成公共方法
 const awaitWrap = (promise) => {
  return promise
   .then(data => [null, data])
   .catch(err => [err, null])
 }

 const [err, data] = await awaitWrap(fetchData())
 console.log('err', err)
 console.log('data', data)
 // err null
 // data fetch data is me
})()

将对 await 处理的方法抽离成公共的方法,在使用 await 调用 awaitWrap 这样的方法是不是更优雅了呢。如果使用 typescript 实现大概是这个样子

function awaitWrap<T, U = any>(promise: Promise<T>): Promise<[U | null, T | null]> {
 return promise
  .then<[null, T]>((data: T) => [null, data])
  .catch<[U, null]>(err => [err, null])
}

以上。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
DIV菜单层实现代码
Nov 19 Javascript
浅析document.createDocumentFragment()与js效率
Jul 08 Javascript
Jquery获取元素的父容器对象示例代码
Feb 10 Javascript
javascript中setTimeout和setInterval的unref()和ref()用法示例
Nov 26 Javascript
js封装可使用的构造函数继承用法分析
Jan 28 Javascript
js根据鼠标移动速度背景图片自动旋转的方法
Feb 28 Javascript
javascript设计模式之对象工厂函数与构造函数详解
Jul 30 Javascript
jQuery实现元素的插入
Feb 27 Javascript
vue教程之toast弹框全局调用示例详解
Aug 24 Javascript
Vue编写多地区选择组件
Aug 21 Javascript
SVG动画vivus.js库使用小结(实例代码)
Sep 14 Javascript
关于React Native使用axios进行网络请求的方法
Aug 02 Javascript
新年快乐! javascript实现超级炫酷的3D烟花特效
Jan 30 #Javascript
JavaScript之解构赋值的理解
Jan 30 #Javascript
JS实现点击按钮随机生成可拖动的不同颜色块示例
Jan 30 #Javascript
JS实现的新闻列表自动滚动效果示例
Jan 30 #Javascript
谈谈为什么你的 JavaScript 代码如此冗长
Jan 30 #Javascript
JS实现头条新闻的经典轮播图效果示例
Jan 30 #Javascript
AJAX在JQuery中的应用详解
Jan 30 #jQuery
You might like
php代码优化及php相关问题总结
2006/10/09 PHP
phplock(php进程锁) v1.0 beta1
2009/11/24 PHP
php+MySQL判断update语句是否执行成功的方法
2014/08/28 PHP
PHP5.5.15+Apache2.4.10+MySQL5.6.20配置方法分享
2016/05/06 PHP
PHP7新功能总结
2019/04/14 PHP
windows系统php环境安装swoole具体步骤
2021/03/04 PHP
关于 byval 与 byref 的区别分析总结
2007/10/08 Javascript
js获取url中&quot;?&quot;后面的字串方法
2014/05/15 Javascript
jQuery中click事件的定义和用法
2014/12/20 Javascript
DOM基础教程之事件类型
2015/01/20 Javascript
JavaScript的removeChild()函数用法详解
2015/12/27 Javascript
详解nodejs express下使用redis管理session
2017/04/24 NodeJs
关于使用axios的一些心得技巧分享
2017/07/02 Javascript
javascript 中select框触发事件过程的分析
2017/08/01 Javascript
vue实现pdf导出解决生成canvas模糊等问题(推荐)
2018/10/18 Javascript
在layui中layer弹出层点击事件无效的解决方法
2019/09/05 Javascript
jQuery三组基本动画与自定义动画操作实例总结
2020/05/09 jQuery
实例讲解React 组件
2020/07/07 Javascript
uniapp实现可滑动选项卡
2020/10/21 Javascript
解决vue 使用axios.all()方法发起多个请求控制台报错的问题
2020/11/09 Javascript
Python and、or以及and-or语法总结
2015/04/14 Python
Python标准库defaultdict模块使用示例
2015/04/28 Python
Python实现截屏的函数
2015/07/26 Python
Python使用QQ邮箱发送Email的方法实例
2017/02/09 Python
python实现各进制转换的总结大全
2017/06/18 Python
Python实现将数据框数据写入mongodb及mysql数据库的方法
2018/04/02 Python
python2.7和NLTK安装详细教程
2018/09/19 Python
解决python 找不到module的问题
2020/02/12 Python
使用celery和Django处理异步任务的流程分析
2020/02/19 Python
Python字典fromkeys()方法使用代码实例
2020/07/20 Python
国际鲜花速递专家:Floraqueen
2016/11/24 全球购物
PAUL HEWITT手表美国站:德国北部时尚生活配饰品牌,船锚元素
2017/11/18 全球购物
应届大专毕业生个人自荐信
2013/09/22 职场文书
函授大学生自我鉴定
2014/02/05 职场文书
西式结婚主持词
2014/03/14 职场文书
党课知识竞赛主持词
2014/04/01 职场文书