当然实际项目中不可能只有一行 console,这是为了说明原理的简化版。
代码中的 httpErrorHandler 会接收 API 的响应错误,并对错误的状态码做不同的处理,所以代码中需要很多 if(或者 switch)判断当前需要要执行什么,当你要对新的错误添加处理代码时,就必须要到 httpErrorHandler 中修改代码。
虽然免不了要经常修改代码,但是这样做可能会导致几个问题,下面根据 SOLID 的 单一职责(Single responsibility)和开放封闭(open/close)这两个原则来说明:
单一职责(Single responsibility)
简单的说,单一职责就是只做一件事情。而前面的 httpErrorHandler 方法以使用的角度来说,是把错误对象交给它,让它按照错误码做对应的处理。看上去好像是在做“错误处理”这个单一的事情,但是从实现的角度上来说,它把不同错误的处理逻辑全部写在了 httpErrorHandler 中,这就会导致可能在只想要修改对错误码为 400 的逻辑时,但是不得不阅读一大堆不相关的代码。
开放封闭原则(open/close)
开放封闭原则是指对已经写好的核心逻辑就不要再去改动,但同时要能够因需求的增加而扩充原本的功能,也就是开放扩充功能,同时封闭修改原本正确的逻辑。再回过头来看 httpErrorHandler,如果需要增加一个对错误码 405 的处理逻辑(要扩充新功能),那就需要修改 httpErrorHandler 中的代码(修改原本正确的逻辑),这也很容易造成原来正确执行的代码出错。
既然 httpErrorHandler 破绽这么多,那该怎么办?
解决问题
分离逻辑
先让 httpErrorHandler 符合单一原则。首先把每个错误的处理逻辑分别拆成方法:
- const response400 = () => {
- console.log('你是不是提交了什么奇怪的东西?');
- };
- const response401 = () => {
- console.log('需要先登陆!');
- };
- const response403 = () => {
- console.log('是不是想偷摸干坏事?');
- };
- const response404 = () => {
- console.log('这里什么也没有…');
- };
- const httpErrorHandler = (error) => {
- const errorStatus = error.response.status;
- if (errorStatus === 400) {
- response400();
- }
- if (errorStatus === 401) {
- response401();
- }
- if (errorStatus === 403) {
- response403();
- }
- if (errorStatus === 404) {
- response404();
- }
- };
虽然只是把每个区块的逻辑拆成方法,但这已经可以让我们在修改某个状态码的错误处理时,不用再到 httpErrorHandler 中阅读大量的代码了。
仅仅是分离逻辑这个操作同时也让 httpErrorHandler 符合了开放封闭原则,因为在把错误处理的逻辑各自拆分为方法的时候,就等于对那些已经完成的代码进行了封装,这时当需要再为 httpErrorHandler 增加对 405 的错误处理逻辑时,就不会影响到其他的错误处理逻辑的方法(封闭修改),而是另行创建一个新的 response405 方法,并在 httpErrorHandler 中加上新的条件判断就行了(开放扩充新功能)。