前言
有人突然问了我这么一个问题,说后端传过来的数据,HTTP状态码(以下简称HTTP码)是200,响应体的code是500,这种操作怎么理解?到底是200还是500?
我本以为,这叫啥问题,结果。。憋了半天我竟一时不知道怎么回答。。
今天彻底搞清楚!
RESTful
RESTful是想尽办法利用现有的HTTP协议的各个“成员”,比如Method就把PUT、PATCH、DELETE这种方法都用上了,那么HTTP码这么好用的东西是一定是要用的。而且,RESTful根本就不允许你在响应体里写{code: 200}
这种鬼。
项目现状
回到项目现状中,在请求体里写{code: 200}
几乎成了某些人眼里的业界规范了啊!HTTP码无脑200啊!这咋解释?!
其实很好解释,这就是半瓶子咣当的程序员对于HTTP码理解错误,前端对后端说一句:“你要给我返回状态码啊”,后端就屁颠屁颠的把码放到请求体里了,前端看到后,心想:“又不是不能用,算了,反正绝大多数情况下都是200”。所以,到今天,搞得这成了业界标准一样。而且一些框架本身就使用HTTP码200、code 500来报错。
从业界来说,
结果成了:
脑子比较清醒的程序员,用HTTP码表达状态,用axios拦截器对各种HTTP码做了处理。
脑子不清醒的程序员,用code表达状态,axios拦截这个code,当然,最后肯定能跑通。但是,这显然是不规范的。
常用状态码都有什么?
建议不要超出这几个,这几个足够用。
200请求成功
201创建成功 专门用于创建新的记录的时候
301永久重定向 网址永久变更成另外一个网址
302临时重定向 网址临时变更成另外一个网址
400无效的请求 请求的网址无效等
401没有登录 需要登录才能访问
403没有权限 虽然登陆了,但是没有权限
404请求资源不存在 请求的东西不存在,比如某个人的信息
500服务器端错误 服务器端发生了错误
业界大公司,谁在用{code: 200}
?
一个不存在的公司,FaceBook,就在用{code: 200}
。谷歌等公司在用状态码200。再比如现在有个流行的java+vue后台系统,若依,官方演示的code我们看一下,它不是{code: 200}
:
HTTP码不是200的话,能返回响应体么?
当然能,包括HTTP 404错误,都能返回你想要的JSON格式的响应体。
只在HTTP码写,前端能精准捕获吗?
这个问题才是核心关键!
你在HTTP码写的飞起,但前端捕获不了,不也是白扯么?
我们测一下:
原生Fetch
成功时:
服务器返回404时:
跨域,但目标服务器无效时:
jQuery
这种方法是可以精确捕获各个错误代码的:
$.ajax({
dataType: "json",
url: 'goodsList.json',
statusCode: {
200: function(err) {
console.log(err);
},
404: function(err) {
console.log(err);
}
},
});
成功时:返回JSON本身。
404出错时:
axios
利用响应拦截器拦截一下:
axios.interceptors.response.use(
function (response) {// 对响应数据做点什么
return response;
},
function (err) {
console.log(err.response);
}
);
成功时:
404出错时,err.response
打印:
结论
市面上主流的ajax库和原生Fetch都支持捕获404,而且都是存放在response.status
。其他的HTTP码也都是一样的道理,就不多说了。
所以,有什么理由不使用HTTP码呢??
HTTP码到底怎么定?
成功的状态码一定是200,就行了。
关于失败的状态码,我专门说一下,其实并没有什么一定之规,只要保证:如果使用常见的HTTP状态码,一定要符合通常理解的规范;如果使用了自定义的状态码,比如1000以上的状态码,那就团队自己定就好了,定了就要遵守,别经常变来变去。
msg
只是在弹窗里显示,不要拿msg
当做出错的判定依据,必须只拿HTTP码当做依据。
最后一个问题,响应体应该怎么写?
先说GET的响应体
{
msg: null,
rows: [...],
total: 14
}
不要写code,不要写code,不要写code!
msg在200前提下就null,因为成功前提下没有必要弹窗提示,除非极少数场合真的需要弹窗提示,不在200前提下可以写明到底什么出了错。msg的内容就是给中国用户看的可阅读的提示,会由前端组件放到提示框里,因此,绝对不要写“success”或者“err”这种鬼!!
rows也可以叫list,强调的是数组解构,空数组则返回
[]
。不是数组的话,也可以叫result,result可以是基本类型也可以是一个对象。不要使用data
作为字段,因为data
意义不明确。尽管现在业界普遍使用data
,但是加上axios封装响应体也会加上data
,结果会写成data.data
这种取值,很容易脑子短路。不要字段套字段,应尽量扁平。
total是可选属性,表示数组资源总数。还可以加其他的字段传递别的数据。
在HTTP码不是2开头的情况下,除了msg,不要有其他属性。
然后说POST、PUT、DELETE的响应体
{
msg: '修改成功'
}
如果200前提下,就返回
msg
就可以了,修改就是“修改成功”,删除就是“删除成功”,新增就是“新增成功”、“创建成功”等等的。总会有失败的可能,比如删除失败,资源被别人先删了,你再删就是删除失败,这时候HTTP状态码不应是200(具体是多少看你们团队的规范),
msg
应当是删除失败:资源已被删除
这类提示。
其他的,比如“支付成功”和“支付失败”,一般来讲,成功,则页面路由会变化,进入下一个环节,失败,则原地弹出提示,可能要求用户换一种支付方式或者放弃支付,因此,失败的HTTP状态码不应是200(具体是多少也看你团队的规范),msg
应当是支付失败:卡余额不足
这类的话。