前言
通常,我们在axios的响应拦截器里写的最多的就是根据HTTP状态码来做出对应的响应,最常见的就是状态码为500的时候,做出不同于200的处理,这个处理有至少3种“流派”:
-
在拦截器里只toast,伪代码即
toast(res.data.msg)
,别的什么也不管,后续处理交给业务代码,于是业务代码里须各种if,比如if (res.statusCode === 500) {...}
-
在拦截器里只return一个reject,不toast:
return Promise.reject(res);
- 前二者的结合体:
toast(res.data.msg);
return Promise.reject(res);
到底哪种更科学一点?
先否掉toast流派
其实toast流派的思想是,toast的内容由后端编写,因此,在前端开发、测试的过程中就会出现问题:
-
后端写msg不一定适合阅读,比如简书自己,当axios出现超时,会在页面顶部弹出
axios timeout error
(大致是这样,记不太清楚了),你让一群写风花雪月的写手看这个,能看出个寂寞?当发现提示语有问题,需要改,就必须去找后端改,然而我们通常认为,toast显示什么提示属于前端程序员管的事,不应该由后端写死。 -
业务流程中并不是凡出错就必须弹出提示,但是toast流派没办法知道哪些提示需要提示,哪些只给前端程序员看看就好。
然后说说toast流派的优点:比较无脑。但是这其实不是优点。
所以toast并不是可行方案。
由于toast方案并不是可行方案,因此也导致“结合体”方案同样不是好的方案。
reject方案好不好?
reject方案的实质是将返回res对象改成了返回失败的Promise对象,它的思想是任何操作都有可能有成功和失败2种状态,我们先看看如果不用reject方案,业务代码一般会怎么写:
this.$axios.get('...A接口...').then((res) => {
if (res.status === 200) {
// 只有 200 状态码会进入这个流程
// ...
return this.$axios.get('...B接口...')
} else if (res.status === 500) {
// 只有 500 状态码会进入这个流程
// ...
toast(res.data.msg)
}
}).then((val) => {
if (res.status === 200) {
// 只有 200 状态码会进入这个流程
// ...
return this.$axios.get('...C接口...')
} else if (res.status === 500) {
// 只有 500 状态码会进入这个流程
// ...
toast(res.data.msg)
}
})
然后看看如果用reject方案,会怎么写:
this.$axios.get('...A接口...').then((res) => {
// 只有 200 状态码会进入这个流程
// ...
return this.$axios.get('...B接口...')
}, (err) => {
// 只有 500 状态码会进入这个流程
// ...
toast(res.data.msg)
}).then((res) => {
// 只有 200 状态码会进入这个流程
// ...
return this.$axios.get('...C接口...')
}, (err) => {
// 只有 500 状态码会进入这个流程
// ...
toast(res.data.msg)
})
可见:reject方案代码更清晰,代码更少。
如果有2种以上的状态,怎么区分resolve分支和reject分支?
比如某接口,返回结果可能有4种状态:
- 完全成功
- 部分成功,另外部分未知
- 部分成功,另外部分失败
- 全失败
这时候怎么区分这4种状态?
-
应当根据上下文,首先区分出成功状态和失败状态。比如前三种认为是成功,后2种认为是失败。怎么区分就看团队内怎么商议了。
-
根据响应体的status字段区分3种成功,比如status: "abc"、status: "def"、status: "ghi"。同样的,根据status区分2种失败,比如status: "uvw"、status: "xyz"。注意,不要用数字,因为数字相当于“魔术值”,看不出表达的意思。
注意,这里用的字段是status,而不是code。响应体就不应该使用code,更不能让响应体code取代真正的HTTP状态码,有人说响应体里的code是用于写200、500、403这种错误码。你可拉倒吧,你被业界一些蠢人带偏了多少年还不自知!
- 在then的成功回调里,用
if(res.data.code === 2001) {}
等3个if来处理不同的成功逻辑,在失败回调里用if(res.data.code === 5001) {}
等2个if来处理不同的失败逻辑。
所以toast应该在哪写?
应当在业务代码和unhandledrejection事件里写。
-
toast应该在业务代码里写,如果前端程序员觉得后端给的msg写的不错,就不要写回调,交给unhandledrejection,如果后端写的msg读起来很渣,就重写,然后toast即可。
-
unhandledrejection负责兜底。
网友评论