9

前端最基础的就是 HTML+CSS+Javascript。掌握了这三门技术就算入门,但也仅仅是入门,现在前端开发的定义已经远远不止这些。前端小课堂(HTML/CSS/JS),本着提升技术水平,打牢基础知识的中心思想,我们开课啦(每周四)。

axios 日常使用上,感觉不如 $.ajax 但是我之前使用的时候不是改入参就是改方法反正是都解决了。
我也知道问题出在 content-type 上。
就是记不住,这不前几天后台项目起了个新的服务。
之前用的构建开发工具用的是 proxy 代理,不知道有老哥用过没,好几年前初次开发的时候就不更新了,还有 bug
索性换 axios 代理一下吧,然后报错了。好吧,我的锅,我认真总结,保证我不忘了。

今天讲什么?

  1. content-type 是什么
  2. MIME 对照表
  3. axios 为什么感觉不如 $.ajax
  4. 带你领略 axios 正确打开方式

content-type 是什么

Content-Type 实体头部用于指示资源的 MIME类型 media type
在响应中,用来描述服务端实际发送给客户端的数据的类型
在请求中,比如 POST请求,是指客户端给服务器实际发送的数据的类型
双方根据这个值,来选择适合的方式解析数据。

MIME 类型组成方式

type/subtype,如application/jsontext/htmltext/plain
对大小写不敏感,但是习惯写小写

content-type 组成方式

Content-Type:media-type; charset,如Content-Type: text/html; charset=utf-8

表单中的应用

<form action="/" method="post" enctype="multipart/form-data"> 想上传文件的时候
<form action="/" method="post" enctype="application/x-www-form-urlencoded"> 默认
为什么想上传文件不能用第二个呢?带着你的问题往后看吧

MIME 对照表

Media Types -全量的对照表

MIME 分类

type关键词 描述 示例
text 文本。复制粘贴的里面常见。 text/html html页面, text/css css文件,text/plain 通用文字(默认格式)
image 图片。input.files[0].type 返回的时候用于判断类型。input accept="image/*" 允许选择所有图片文件 image/png png图片, image/jpeg jpg图片
audio 音频。同上 audio/wav,audio/mpeg mp3文件
video 视频。同上 video/mp4 MP4文件
application 二进制数据 application/octet-stream 通用类型(默认格式),application/pdf
multipart 复合类型 multipart/form-data

常见 MIME

key 描述
application/octet-stream 默认值,或者可以理解为未知的应用程序文件浏览器会像对待设置了 HTTP 头 Content-Disposition 值为 attachment 的文件一样来对待这类文件。(微信下载文件)
text/html 可以理解为 html、xml 文件。
text/plain 默认值,也可以理解为未知格式的文本文件。文本文件嘛,没格式就只看字也不是啥大问题
image/png 常见图片类型,一般上传图片的时候判断
image/jpeg 常见图片类型,一般上传图片的时候判断
image/gif 常见图片类型,一般上传图片的时候判断
multipart/byteranges 用于把部分的响应报文发送回浏览器。常见于请求视频资源返回206状态码
application/json JSON 格式
multipart/form-data 用于带文件上传的表单提交。作为多部分文档格式,由边界线(一个由'--'开始的字符串)划分出的不同部分组成。每一部分有自己的实体,以及自己的 HTTP 请求头,Content-DispositionContent-Type
application/x-www-form-urlencoded 普通的 get&post 请求。数据被编码为键/值对(a=1&b=2)这是标准的编码格式。

axios 为什么感觉不如 $.ajax

(同样代码 jquery 好使,axios 不好使,axios 有 bug 吧)-这个应该是我听到最多的吐槽了。测试地址

axios 与 $.ajax 设计思路、或者说历史场景

  1. jquery 非常棒,他存在解决了各个浏览器版本不一致的问题,提供了统一的 api,极大的简化了我们的操作。
  2. axios 拥抱现代浏览器,提供跨平台(Node发请求)、 Promise等。

get 请求

对于 get 请求其实没有太多说的,请求的参数会拼在 url 上,如 https://www.lilnong.top/CORS/lnong?a=1&b=2,其中 a=1&b=2 就是带过去的参数

同样两个使用,我们会发现 axios 的没有带过去参数。
clipboard.png
clipboard.png
这个时候兄弟们就开始说,我写了为什么传不过去。垃圾垃圾。针对上面的问题兄弟们骂完之后,还是要解决问题的。

  1. 手动拼写,兄弟也是虎的可以
    clipboard.png
  2. qs$.param({a:1,b:2}) 等类库解决处理问题,然后手动拼接
  3. 正确答案(axios 是使用 params 来发送 get 的数据的)
    clipboard.png

post 请求

clipboard.png
对于 post 请求来说就有好几种情况了

  1. application/x-www-form-urlencoded 这种情况等于把 get 方式的参数拿到 请求体中存放。编译格式是一模一样的。
  2. application/json 请求体中就是如下的JSON字符串{a:1,b:2}
  3. multipart/form-data 请求体中就是这种块的结构。
    clipboard.png

好,那我们接着看兄弟们为什么要吐槽。同样,我 ajax 怎么好使,axios ****
clipboard.png

  1. data 不行,我们换 params,嗯这里其实分为两个情况

    1. 后台大哥说收到了,嗯,post 也是 params的结论就出来了
    2. 过几天另一个后台大哥说收不到。很奇怪,又开始揪头发。
    3. 这里说一下为什么有的时候能收到,有的时候不行。首先 params 带过去的参数会拼写在 url 上。如果严格来按规定做的话,他就是拿body 的信息就导致拿不到。不按规定来,url的构建一次,body的覆盖一次,就导致拿到了。
  2. 有的人比较机灵,换 params 发现不怎么好使,突然发现官网的例子,我来试一试。后台大哥怎么还收不到?这里其实 content-type 被改成了 application/json。一般来说老后台都不会适配这种格式。axios({method:'post'}) 也是这种格式
    clipboard.pngclipboard.png
  3. 没办法了?嗯,他们又开始自己拼接。嗯,这次有混过去了
    clipboard.png
  4. transformRequest 大法,我这个方法里面,给他处理一番。
    clipboard.png
  5. FormData 大法好,精准识别,也算是正确的表单提交。
    clipboard.png
  6. URLSearchParams 方案等同于 Qs 的类库,只不过是浏览器支持的,当然兼容性也不怎么样
    clipboard.png

带你领略 axios 正确打开方式

  1. 使用 get 要用 params 来发送请求
  2. 使用 post 要用 data 来发送请求

    1. 默认为 application/json 格式
    2. 可以通过 FormData 来进行修改
    3. 更建议全局 transformRequest 的方案
  3. axios 支持 Promise

    axios.get('/user?ID=12345')
      .then(function (response) {
        console.log(response);
      })
      .catch(function (error) {
        console.log(error);
      });
  4. axios 支持 Node 环境
  5. 配置默认值,方案1更痛快,可以增加一些通用的 headers

    1. 全局的 axios 默认值

        axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
    2. 实例默认值

        // 创建实例时设置配置的默认值
        var instance = axios.create({
          baseURL: 'https://api.example.com'
        });
        
        // 在实例已创建后修改默认值
        instance.defaults.headers.common['Authorization'] = AUTH_TOKEN;
  6. 拦截器,可以拦截错误,进行上报。或者打印日志。

    // 添加响应拦截器
    axios.interceptors.response.use(function (response) {
        // 对响应数据做点什么
        return response;
      }, function (error) {
        // 对响应错误做点什么
        return Promise.reject(error);
      });

总结

content-type 很重要,在 req 中是告知服务器应该用什么样的格式去解析数据,rsp 中是让浏览器端去如何解析数据。
根据对应的类型,传对应的格式,才可以正确的收发。

参考资料

  1. MIME 类型 --MDN
  2. axios --看云

linong
29.2k 声望9.5k 粉丝

Read-Search-Ask