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,返回的格式通过数组进行统一)

相关推荐
小远yyds17 分钟前
前端Web用户 token 持久化
开发语言·前端·javascript·vue.js
阿伟来咯~1 小时前
记录学习react的一些内容
javascript·学习·react.js
吕彬-前端1 小时前
使用vite+react+ts+Ant Design开发后台管理项目(五)
前端·javascript·react.js
学前端的小朱1 小时前
Redux的简介及其在React中的应用
前端·javascript·react.js·redux·store
guai_guai_guai1 小时前
uniapp
前端·javascript·vue.js·uni-app
也无晴也无风雨1 小时前
在JS中, 0 == [0] 吗
开发语言·javascript
bysking2 小时前
【前端-组件】定义行分组的表格表单实现-bysking
前端·react.js
王哲晓3 小时前
第三十章 章节练习商品列表组件封装
前端·javascript·vue.js
fg_4113 小时前
无网络安装ionic和运行
前端·npm
理想不理想v3 小时前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试