如何优雅地退出函数

退出函数怎么写?有人会说一个 return 就退出函数了,有这么简单吗?来看一个表单校验和提交结果的函数:

js 复制代码
// 表单校验
function validate() {}
// 提交表单
function submit() {
  validate();// ?如果表单校验失败怎么退出函数呢?
  fetch("/api/submit", {
    // ...
  });
}

如果表单校验失败怎么退出函数呢?传统的思维方式必然是使用return解决,让 validate 函数返回一个值来判断是退出函数还是继续执行:

diff 复制代码
function validate() {}
function submit() {
+  if (!validate()) {
+    return;
+  }
  fetch("/api/submit", {
    // ...
  });
}

这样解决是可以的,但是不够优雅,为什么呢?因为 validate 函数本身是不需要返回值的,现在却为了功能必须添加一个返回值,并且 submit 函数还依赖于 validate 的返回值,增加了函数之间的耦合度。如何优雅地退出函数,这就是今天的主题。

抛出异常

第一个方法当然是抛出异常,这一招我屡试不爽,还是上面那个案例,先看看如何通过抛出异常退出函数:

diff 复制代码
// 表单校验
function validate() {
+    throw new Error("验证失败");
}
// 提交表单
function submit() {
  validate();// ?如果表单校验失败怎么退出函数呢?
  fetch("/api/submit", {
    // ...
  });
}

如果 submit 还有其他很多流程并且这些流程中的某个分支也需要退出整个 submit 函数,使用抛出异常退出函数的话就不需要写那么多的 if else 了,例如:

js 复制代码
// 提交表单
function submit() {
  validate();// ?如果表单校验失败怎么退出函数呢?
  doSomething1(); 
  doSomething2();
  fetch("/api/submit", {
    // ...
  });
}

但是这种方式也有一个弊端,那就是带来了控制台的爆红,不过一看就看得出来这不是程序报错导致的,是我们手动抛出的:

抛出异常这种方式在异步函数中同样适用,但是需要改变写法,先来看看不改变写法会怎么样:

diff 复制代码
+ async function validate() {
  throw new Error("validate failed");
}
+ async function submit() {
  validate();
  fetch("/api/submit", {
    // ...
  });
}

咦,为什么抛出异常不生效了呢,要解答这个问题,首先得把这段代码"翻译"一下:

diff 复制代码
function validate() {
+  return Promise.reject(new Error("validate failed"));
}

显然这里函数没有真正抛出异常,而是被 Promise 拦截掉了,导致退出函数失败。这里只需要增加一个 await 就可以退出函数了:

diff 复制代码
async function submit() {
+  await validate();
  fetch("/api/submit", {
    // ...
  });
}

异步函数 reject

上面说了抛出异常可以退出异步函数,但是不仅仅这一种方式,还可以通过 Promise.reject 退出异步函数:

diff 复制代码
async function validate() {
  return Promise.reject();
}

所以如果想退出函数可以先将函数改为 async 函数,然后返回一个 reject 状态的 Promise,这样就能够退出函数了。

最后,总结一下所有退出函数的方法:

  1. 函数返回一个布尔值,根据这个布尔值判断是否 return 退出函数
  2. 抛出异常退出函数,注意异步函数需要加上 await,否则无法退出
  3. 将普通函数转为异步函数,然后返回一个 reject 状态的 Promise,也可以实现退出函数的目的
相关推荐
小墨宝28 分钟前
js 生成pdf 并上传文件
前端·javascript·pdf
HED43 分钟前
用扣子快速手撸人生中第一个AI智能应用!
前端·人工智能
DN金猿1 小时前
使用npm install或cnpm install报错解决
前端·npm·node.js
丘山子1 小时前
一些鲜为人知的 IP 地址怪异写法
前端·后端·tcp/ip
志存高远661 小时前
Kotlin 的 suspend 关键字
前端
www_pp_1 小时前
# 构建词汇表:自然语言处理中的关键步骤
前端·javascript·自然语言处理·easyui
YuShiYue2 小时前
pnpm monoreop 打包时 node_modules 内部包 typescript 不能推导出类型报错
javascript·vue.js·typescript·pnpm
天天扭码2 小时前
总所周知,JavaScript中有很多函数定义方式,如何“因地制宜”?(ˉ﹃ˉ)
前端·javascript·面试
一个专注写代码的程序媛2 小时前
为什么vue的key值,不用index?
前端·javascript·vue.js
장숙혜2 小时前
ElementUi的Dropdown下拉菜单的详细介绍及使用
前端·javascript·vue.js