axios从入门到源码分析

83 阅读8分钟

axios从入门到源码分析

.axios是什么?

axios:基于promise封装的ajax库,基于这个类库发送ajax请求,默认就是基于promise管理的,核心还是XMLHttpRequest

axios中文文档8|axios中文网 | axios

axios中GET系列的使用方法?

1.首先需要导入axios对应插件:

 npm i axios
    <script src="node_modules/axios/dist/axios.min.js"></script>

2.GET系列  axios.get([url],[config]) 请求URL地址、配置项

axios.get/head/delete/options/post/put/patch 发送对应类别请求的方法

[url]: 放我们请求资源的对应接口路径,==不带参数==

[config] :用来配置请求信息,是一个对象类型,==每个属性按照键值对的形式配置==

我们配置的这些属性实际上是在给这次请求的xhr实例设置私有属性,不要以为都是在给请求头设字段。

1. params:[string/object] 基于问号参数方案,需要传递给服务器的信息

如果传递的是个对象,axios内部会把对象变为 xxx=xxx&xxx=xxx 这样的字符串,然后基于问号参数传递给服务器;如果写的是一个字符串,则变为 0=字符串 的方式传递给服务器;我们一般都使用对象的方式!!

2. timeout:[number]` :请求超时时间,数字类型但为是==ms==

3. withCredentials:[boolean] :==默认为false==,true:表示允许跨域携带资源凭证,false:表示不允许

4.responseType:[string] :把服务器返回的结果转为对应的数据格式,默认是`json

(==服务器返回的结果,我们都把它转为json对象==),

还有其他类型:'arraybuffer/blob/document/json/text/strem';

5.onUploadProgress:[function]: 监听文件上传进度

6.baseUrl:[string] :配置请求地址的前缀

7.validateStatus:[function] :里面是一个函数,函数中的return可以配置`

status`决定状态值在什么范围才算请求成功,默认2xx为请求成功

8. **headers:{"Name":"lisa"}:** 可以通过headers给请头添加我们想传的数据

axios中POST系列的使用方法?

1.首先需要导入axios对应插件:

 npm i axios
    <script src="node_modules/axios/dist/axios.min.js"></script>

2.==axios中post的创建方式==:axios.post([url],[data],[config]);对应的put/patch方法

    • url:字符串类型,请求的目标路径
    • [data]:可以是字符串类型,可以对象类型,post中请求体的信息,如同xhr.send(),中传的数据,但一般不会传字符串。
    • [config]:**对象类型,**配置请求的配置项

axios中POST请求的请求主体

  • data就是请求体信息:发送之前,会在内部默认处理称为==JSON字符串==,再传给服务器

  • 如果服务器想要的不是JSON字符串,可以将[data]值设置为服务器想要的字符串。

  • 如果服务器想要的是urlencoded字符串,我们有两种方式做处理:

  • 方式一:【引入Qs库】,基于Qs.stringify/parse做处理:axios.post([url],Qs.stringify(data),[config]);

  • Qs.stringify(data):将对象转为urlencoded字符串

  • Qs.parse(data):将urlencoded字符串转为对象

  • 方式二:使用transformRequest:function ([data],[heders]){return xxx} 的方式,自行改成想要的格式。

  • ==axios内部做了一个非常有用的事情==:根据我们传递给服务器的内容格式,自动帮我们设置请求头中的 Content-Type ,让其和传递的格式相匹配「MIME类型」不需要设置headers

    • urlencoded格式字符串 : Content-Type:'application/x-www-form-urlencoded'
    • json格式字符串 :Content-Type:'application/json'
    • FormData格式对象: Content-Type:'multipart/form-data'

Qs.stringify(data):将对象转为urlencoded字符串 必须是纯对象

对象分为几大类?
  • 对象类型「引用数据类型」

    • 标准普通对象 object
    • 标准特殊对象 Array、RegExp、Date、Math、Error……
    • 非标准特殊对象 Number、String、Boolean……
    • 可调用/执行对象「函数」function

加密:md5

加密:对称加密(可逆转加密,加密完可以解密,)一般自己设定规则

非对称加密(不可逆转的加密)一般使用md5加密

.基于axios发送的请求,返回结果都是promise实例

    • 数据请求成功会让promise状态为成功,promise值就是从服务器获取的结果
    • 数据请求失败会让promise状态为失败
axios.get('http://127.0.0.1:9999/user/list', {
    timeout: 1,
    params: {
        departmentId: 0,
        search: ''
    }
}).then(response => {
    console.log('请求成功:', response);
    // response对象
    //   + status/statusText HTTP状态码及其描述
    //   + request 原生的XHR对象
    //   + headers 存储响应头信息(对象)
    //   + config 存储发送请求时候的相关配置项
    //   + data 存储响应主体信息
    return response.data;
}).then(value => {
    console.log('响应主体信息:', value);
}).catch(reason => {
    console.log('请求失败:');
    console.dir(reason);
    
}); 
 

.axios做get请求时存在的三种错误情况?

==有响应体== :返回的错误对象中有状态码:response->status,没有code

- ==无响应体==:

    • timeout:请求超时或被中断,没有状态码,有code属性:code:"ECONNABORTED" response:undefined
    • navigator.onLine=false(断网)时:没有状态码,也没有code和response,只能用navigator.onLine=false判断。

.axios的get和post请求另一种写法?

axios({
        method: 'get',
        url:'http://127.0.0.1:9999/user/list',
        params:{id:1},//重点,get方法中用params
        headers:{}
    }).then(res=>{
        console.log(res);
})
 
axios({
        method: 'post',
        url:'http://127.0.0.1:9999/user/list',
        data:{id:1},//重点,post方法中才能有data
        headers:{}
    }).then(res=>{
        console.log(res);
})
二次封装

==提取公共配置==:axios的二次封装就是将所有请求的公共部分提取到一个默认的js文件中,所有的请求都会遵循这个默认配置文件。

*默认配置 :axios.defaults.xxx;->xxx:是能够配置的配置项,如timeout

==单独配置== :单独写的请求配置,优先级高于公共配置

 axios.defaults.baseURL = 'http://127.0.0.1:9999';//设置公共 前缀路径
      
      axios.defaults.transformRequest = data => {//设置公共 转换请求体格式
          if (isPlainObject(data)) return Qs.stringify(data);
          return data;
      };
      axios.defaults.timeout = 60000;//设置公共 请求超时时间

axios的请求、响应拦截器怎么使用?

  • 请求/响应拦截器**:axios.interceptors.request/response
    • 基于拦截器进行公共部分提取
    • 请求拦截器:发生在 “配置项准备完毕” 和 “发送请求” 之间
    • 响应拦截器:发生在 “服务器返回结果” 和 “业务代码自己处理 .then” 之间
  //请求拦截
  axios.interceptors.request.use(config => {
  					// config对象包含的就是准备好的配置项,最后返回啥配置,就按照这些配置发请求
    return config;
  });
  • //响应拦截:如果成功就将结果返回给用户,如果失败,进行处理再返回
    axios.interceptors.response.use(response => {
        // 请求成功:把响应主体信息返回给业务层去使用
        return response.data;
    }, reason => {
        // 请求失败:根据不同的失败原因做不同的提示
        if (reason && reason.response) {
            // @1 有返回结果,只不过状态码不对
            let {status} = reason.response;
            switch (+status) {//switch是做===比较
                case 403:
                    alert('服务器不爱搭理你~~');
                    break;
                case 404:
                    alert('你傻啊,地址都错了~~');
                    break;
                case 500:
                    alert('服务器开小差了~~');
                    break;
            }
        } else {
            // @2 请求超时或者中断 
            if (reason && reason.code === "ECONNABORTED") {
                alert('请求超时或者被中断了~~');
            }
            // @3 断网
            if (!navigator.onLine) {
                alert('当前网络出问题了~~');
            }
        }
        // 统一失败提示处理完,到业务代码处,我们还是要失败的状态,这样才能继续做一些自己单独想做的失败处理
        return Promise.reject(reason);
    });
    

### Fetch的使用

ES6新增的一种API Fetch,==是浏览器原生自带的==,核心不是XMLHttpRequest,是基于全新的通信机制实现的[本身是基于promise管理的]

```cobol
 fetch('http://localhost:9999/job/list',{
            method:'GET',
            headers:{},//请求头信息
            //必须是字符串
            // body:JSON.stringify({id:0})//请求体中的参数,GET/HEAD/OPtions/DELETE方法没有请求体,不能有body
        }).then(function(response){
            console.log(response);//获取的是一个响应信息的对象,看不到真正的响应体
            return response.json(); //想要获取响应体的信息,需要调用对应格式的response.xxx()方法
    
        }).then(function(value){
            console.log(value);
        })

注意点

    • GET/DELETE/OPTIONS/HEAD方法中不能存在body。
    • fetch得到的结果是一个Promise对象,可以调用then方法PromiseResult是响应的信息,但找不到响应体信息。
    • 想要获取响应体信息需要调用result对应数据格式的方法,比如想获取json格式的响应数据:result.json()/result.text()/result.formdata()/...
    • ==result.json等格式获取方法只能使用一次,且只能有一种==

axios和Fetch的区别?

  • 他俩都是发送请求的

    • axios是基于promise封装的ajax类库
    • fetch是浏览器原生的API
    • 传参字段不一样,axios是放在params或者data里,fetch是放在body里
    • node环境中不支持fetch,需要引入node-fetch文件才能支持
    • axios中的配置和拦截器等功能,fetch中都没有。

面试题:ajax、$ajax、axios、fetch的区别

==ajax:== 原生的ajax,依赖XMLHttpRequest,再基于ajax的四步操作,实现从服务器获取数据

- ==$ajax:== 是JQ类库对原生ajax的封装,基于回调函数封装的ajax类库

    • 核心:XMLHttpRequest
    • 当请求成功,触发succes回调函数执行,在这个回调函数可以拿到从服务器获取的数据
    • 弊端:在akax的串行中,容易产生回调地狱

- axios: 基于promise封装的ajax库

    • 核心也是XmlHTTPRequest
    • 基于promise更好的管理一部编程
    • 每一次基于axios发送请求,都会返回一个promise实例;
    • ==请求成功==:实例为fulfilled,但是从服务器获取的结果
    • ==请求失败==:实例为rejected,值是失败的原因
  • fetch :ES6新增的方法:

    • 核心告别了XMLHttpRequest的时代,基于新的通信机制实现客户端和服务器端的数据传输
    • 默认就是基于promise管理的
    • 缺点:不兼容IE浏览器(而且@bable/poly没有实现它)

QS库

安装qs库  $ yarn add qs

引入:

 Qs.stringify(obj):把obj对象转换为urlencoded格式的字符串
      "xxx=xxx&xxx=xxx"
      MIME:application/x-www-form-urlencoded
 Qs.parse(str):把urlencoded格式的字符串变为对象

浏览器内置的JSON对象

  JSON.stringify(obj):把obj对象转换为json格式的字符串
      '{"name":"zhufeng",...}'
      MIME:application/json
   JSON.parse(str):把json格式的字符串转换为对象