js异步梳理 & await-to-js解决方案

背景

扫视一遍手里几千行还没被cr的代码,try-catch满屏都是,散落在💩山的角角落落并为之锦上添花!窥视前辈的代码,而是使用了await-to-js提供的to方法这种方式来处理错误,于是对await-to-js心生好奇,并顺便梳理一下js的异步痛点与解决方案,这块虽比较基础,但简单说一说更加流畅一点,对新手更加友好,title都标注好了,大家跳到需要的地方看即可。

js异步痛点

前置理解------js异步

js代码一行接着一行按顺序执行的是同步代码,而需要等待某些条件实现时才触发的代码逻辑是异步代码(异步代码无法预测其执行顺序)。换句话说,同步或者异步代码只是js代码的两种分类,他们有着执行时机上的区别。

保证异步执行顺序------回调地狱

类比js编码,如果我们要实现的功能点是做饭,那么总共分为三个有顺序的步骤:买菜、洗菜最后是炒菜。而且这三个有先后顺序的步骤并不是同步js代码,而是异步代码,那么我们要保证买菜=>洗菜=>炒菜的顺序,就需要进行如下编码:

js 复制代码
async function 买菜() {
  // 处理买菜ing,得到了菜(洗菜需要)
  洗菜();
}
async function 洗菜() {
  // 处理洗菜ing,得到干净的菜(炒菜需要)
  炒菜();
}
async function 炒菜() {
  // 处理炒菜ing
}
// 开始买菜
买菜();

如上代码表达的就是买菜逻辑完成后才触发洗菜的逻辑,洗菜处理完后触发炒菜,等价于:

javascript 复制代码
(async function 买菜() {
  // 处理买菜ing,得到了菜(洗菜需要)
  (async function 洗菜() {
    // 处理洗菜ing,得到干净的菜(炒菜需要)
    (async function 炒菜() {
      // 处理炒菜ing
    })();
  })();
})();

说白了,如上嵌套的唯一目的就是保证异步逻辑之间的执行顺序,为了让洗菜滞后与买菜执行,那么我们编程实现的方式就是在买菜的函数体中定义并执行洗菜(逻辑上嵌套起来了,代码外观上一堆缩进,就是所谓的回调地狱/嵌套地狱)

es6提供的异步嵌套解决方案------promise

使用promise改写如上代码:

js 复制代码
买菜()
.then((菜) => 洗菜)
.then((干净的菜) => 炒菜)

不嵌套了~

进一步优化------async语法糖

一直写.then堆成一长串,肯定不美观,而且炒菜逻辑中无法拿到刚买来的菜(只能拿到干净的菜)。使用async改写如上逻辑:

js 复制代码
async 买菜() {
  const 干净的菜 = await 洗菜(菜);
  const 饭 = await 炒菜(干净的菜); // 也可以 炒菜(菜)
  return 饭;
}
买菜();

异步错误处理

try-catch

如果async函数中某些逻辑抱错,那么可以被其(出错逻辑)外层的try-catch捕获,对

js 复制代码
async 买菜() {
  const 干净的菜 = await 洗菜(菜);
  const 饭 = await 炒菜(干净的菜); // 也可以 炒菜(菜)
  return 饭;
}
买菜();

进行改写:

js 复制代码
async 买菜() {
  try {
    const 干净的菜 = await 洗菜(菜);
    return 饭;
  } catch (error) {
    console.log('处理洗菜错误');
  }
  try {
    const 饭 = await 炒菜(干净的菜);
  } catch (error) {
    console.log('处理炒菜错误');
  }
  return 饭;
}
买菜();

await-to-js

说实话由如上的try-catch示例引出await-to-js我认为并非必要,前者也并没有绝对的后者解决掉的痛点, 所以await-to-js的意义需要大家自己来品味,最后我也会说说我的理解。

上方代码改写:

js 复制代码
async 买菜() {
  const [error1, 干净的菜] = await to(洗菜(菜));
  if(error1) {
    console.log('处理洗菜错误');
  }
  const [error2, 饭] = await to(炒菜(干净的菜));
  if (error2) {
    console.log('处理炒菜错误');
  }
  return 饭;
}
买菜();

try-catch VS await-to-js------我的理解

如上所说:"说实话由如上的try-catch示例引出await-to-js我认为并非必要,前者也并没有绝对的后者解决掉的痛点, 所以await-to-js的意义需要大家自己来品味。"

try-catch优点

  • try-catch可以捕获try作用域块里的所有错误,捕获范围更加灵活

try-catch缺点

  • 丑陋?(我猜的!)

await-to-js优点

  • 只捕获作为to方法参数的promise的错误,捕获更加精确
  • 通过数组解构拿到res与error,代码更加易读

await-to-js缺点

  • 需要引个包?(真编不出来了!)

await-to-js源码实现

删繁就简,丐版核心:

js 复制代码
export default function to(promise) {
   return promise.then(data => {
      return [null, data];
   })
   .catch(err => [err, undefined]);
}

(给接收的promise添加了then和catch,成功就返回data,失败就返回err,返回的格式通过数组进行统一)

相关推荐
nbsaas-boot1 分钟前
消息队列场景下的前端设计:如何优化用户体验
前端·ux
sususugaa3 分钟前
前端框架Vue3——响应式数据,v-on,v-show和v-if,v-for,v-bind
开发语言·前端·vue.js·前端框架
珹洺1 小时前
从 HTML 到 CSS:开启网页样式之旅(三)—— CSS 三大特性与 CSS 常用属性
前端·javascript·css·网络·html·tensorflow·html5
T^T尚6 小时前
uniapp H5上传图片前压缩
前端·javascript·uni-app
出逃日志6 小时前
JS的DOM操作和事件监听综合练习 (具备三种功能的轮播图案例)
开发语言·前端·javascript
XIE3926 小时前
如何开发一个脚手架
前端·javascript·git·npm·node.js·github
GISer_Jing7 小时前
React渲染相关内容——渲染流程API、Fragment、渲染相关底层API
javascript·react.js·ecmascript
山猪打不过家猪7 小时前
React(五)——useContecxt/Reducer/useCallback/useRef/React.memo/useMemo
前端·javascript·react.js
前端青山7 小时前
React事件处理机制详解
开发语言·前端·javascript·react.js
科技D人生7 小时前
Vue.js 学习总结(14)—— Vue3 为什么推荐使用 ref 而不是 reactive
前端·vue.js·vue ref·vue ref 响应式·vue reactive