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

相关推荐
leafyyuki几秒前
两行 CSS 搞定筛选条行尾对齐,Element Plus 表单布局终极方案
前端
着迷不白1 分钟前
六、Bash Shell 与进程管理
前端·chrome
A不落雨滴AI1 分钟前
DKERP 客户端重构:30天从零到一的架构演进之路
前端
Xp021911037 分钟前
知网研学、万方、WPS、大以论文四大排版工具横评,新用户免费排版等你领!
前端·css·html·生活·wps·论文排版
全栈技术负责人7 分钟前
老项目新需求AI前端开发指南
前端·ai编程
周凡12317 分钟前
AI 时代的 Web JavaScript 逆向分析实践与思考
前端·javascript·人工智能
jerryinwuhan22 分钟前
marker BiBERTo解释
java·前端·人工智能
zhoumeina9930 分钟前
分段创建产品,tab 页切换又要保留缓存
前端·javascript
SilentSamsara31 分钟前
命令行工具开发:Click/Typer + 打包为独立二进制
linux·服务器·开发语言·前端·python·青少年编程·fastapi
恋猫de小郭34 分钟前
能在手机本地跑的图像生成模型 Bonsai Image ,效果还不错
前端·aigc·ai编程