“使用抛异常的方式返回校验不通过的结果”是不是一个好的处理方式?

2023-08-14 12:16:10 +08:00
 STtree

我正在写一个 Express 服务,其中有个地方需要校验用户的输入。我的处理是在校验不通过后抛出一个异常,由全局的异常处理来返回 400 响应。我的同事觉得我这种处理方式不行,他的理由如下:

我觉得有些道理,但是我之前写 Java 的时候看到过很多这种用法,而且我觉得这种用法写起来也比较方便。难道这真的不是一个好的处理方式?

3231 次点击
所在节点    Node.js
31 条回复
cxtrinityy
2023-08-14 12:34:10 +08:00
Nodejs 不知道,Java 的确挺常见的,相比于增加的一点性能开销,try catch 带来的好处也不少,这种情况往上抛异常一般表示这个异常你不需要处理,往上抛上层自然有别的方法来处理,一层层往上走即可,直到抛到顶层。如果你自己去处理这套逻辑,可能比较麻烦,容易出错,而且为了这点性能,真的有必要这样作么?这是个平衡问题,不知道同样道理适不适用于 nodejs
airyland
2023-08-14 12:39:34 +08:00
绝大多数网站没有到需要考虑 try catch 性能开销的用户量。
vchroc
2023-08-14 12:42:27 +08:00
是。他的这两个理由都很牵强
makelove
2023-08-14 13:28:08 +08:00
非常合理,这类目的直接返回简单 400 回应的用户输入异常就是 exception 。

除非是表单校验之类预期用户会输入不合理数据并要给出相应提示的情况下不用异常来处理也合理。
picone
2023-08-14 13:33:26 +08:00
理解不一样吧,try catch 倾向于程序处理中的未知错误,表单验证是 if else 能处理的。他是不是 C/Go 等语言过来的😂
dzdh
2023-08-14 13:42:22 +08:00
我理解 try...catch 是处理逻辑异常,TypeError 、BoundsError 也是逻辑上的异常,逻辑上传错了类型,接收错了类型。

程序错误,抛出异常给 500 响应,逻辑异常给 400 响应没毛病
sujin190
2023-08-14 13:44:28 +08:00
验证不通过其实就是输入错误难道不是 error 不应该走 error handling 么?谈 try catch 会增加性能开销那更是扯淡,不是说没有性能开销而是实际业务中纠结这个毫无意义
Chad0000
2023-08-14 13:46:52 +08:00
以前我指向返回 Result 带 Success 与否,现在我直接抛异常,异常类型统一定义方便统一截获处理。比如数据验证异常就可以友好返回。

好处是代码写起来很简洁,Fail First 。
zhengwenk
2023-08-14 13:48:08 +08:00
动不动就性能开销,cpu 和 内存发展的那么快不就是给你开销的么。都不开销,放着看么
fgwmlhdkkkw
2023-08-14 13:50:51 +08:00
try catch 没有开销,跟你正常判断一样。
nothingistrue
2023-08-14 14:48:04 +08:00
如果 “ try catch 会增加性能开销” 有道理, 那不止 Java , 大部分语言都要回炉重造。不过这个确实看语言框架。
“ exception 应该用于 error handling”,这就是纯粹的胡说八道,用户输入校验不通过,这不是错误,那系统就没有错误了。当然,既然用了 exception ,那就得什么样的错误配什么种类的 exception ,别无脑什么错误都抛出同一种 exception(msg )
Masoud2023
2023-08-14 15:03:23 +08:00
Java 基本也只能这么做吧
libook
2023-08-14 15:05:18 +08:00
用 Java 、Node.js 不需要考虑性能问题,大多采取微服务集群的方式就可以消化并发负载,真的是单个请求有性能问题,应该在有问题的这部分使用 C++、Rust 等语言使用高性能方案处理。

个人认为关于代码,最重要的是可读性,其次是可扩展性,最后才是性能。

异常会有很多种,有的需要返回 400 ,有的需要返回 401 ,有的需要返回 403 ,等等。如果你定义好了不同类型的 error ,然后可以根据 error 类别来精准返回错误信息,且同类 error 的返回信息在未来有可能会统一修改,那么全局处理可能会让代码更简洁、清晰一些。你只需要处理好 error 的 stack ,确保未被捕获的 error 可以明确找到真实发生的代码位置就行。

如果你的信息返回格式是碎片化的,那么还不如每个接口自行组织和返回信息。

当然通常肯定都是部分状态可以统一处理,部分状态需要分别处理,那么只需要把适合统一处理的放到全局处理就好了。

没有万能的设计,都是要根据项目当前的需求特点和未来可能的需求来选择采取哪种设计方式。
wuwukai007
2023-08-14 15:11:27 +08:00
接口里调用了 N 个方法,在最后一个方法里 raise 异常直接返回前段,不要太舒服
lsk569937453
2023-08-14 15:11:40 +08:00
相当于讨论"微服务之间的 http 调用是否应该捕获所有异常,然后返回 http status 200,最后在 response body 里面返回异常码和异常信息。"

正方和反方只能说各执一词吧。
wangritian
2023-08-14 15:19:09 +08:00
错误和异常确实要分开处理,比如异常应当越过多级调用直接到最上层,错误要调用层单独处理、错误是普通返回但异常要报警通知、异常返回给用户的信息要脱敏或者简单替换为系统繁忙,等等
很多人嘲笑 go 的 if err ,我认为这是正确处理错误和异常无法避免的操作
Oktfolio
2023-08-14 15:20:17 +08:00
这个说法确实没有问题

不过,在业务代码比较复杂的情况下,抛出异常而不是使用统一返回会让代码更简单易读
sprite82
2023-08-14 15:40:53 +08:00
如果层级不深,或者这个错误很少出现,使用抛异常方式会简单很多。像某些参数校验接口,错误次数一多,内存占用能翻倍,很容易就会 OOM
xloger
2023-08-14 16:33:14 +08:00
身为一名 Java 或者说 Kotlin 用户,我的观念是这样的:
从需求本质看,我们需要的是对一个函数能清晰地得到它的正确状态下的返回值,和可能的失败情况。

那么,Java 的 try catch 是一个比较好的方案,它能不影响正确状态的返回值,并且错误状态能携带额外信息。

而另一种传统的错误码形式,它的返回更冗余,并且还需要对着看,想附加额外的错误信息并不那么方便。简而言之,表达力不够强。

嗯,所以我认为 Result 是最理想最兼顾的方案。关于这点的讨论可以参考: https://www.zhihu.com/question/330263279
mdn
2023-08-14 16:43:53 +08:00
理由太牵强,Nodejs 也可以这样使用,主要是风格/习惯问题

Nodejs 可以使用 https://github.com/jshttp/http-errors

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/965082

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX