axios详细解读

// PostMan 工具测试接口是不考虑跨域的
    // npm i qs
    // npm i blueimp-md5
    /*
      + axios 基于 Promise 封装的 ajax 库 [核心还是基于 XMLHttpRequest 发送请求的]
        + 基于 axios 发送数据请求, 返回结果都是一个 Promise 实例
          + 默认情况下
            + 服务器返回的HTTP响应状态码是以 2 开始, 则让 Promise 状态为成功, 值是一个 response 对象
              response = {
                config: { ... }, // 发送axios请求设置的配置项
                data: { ... },  // 服务器返回的响应主体信息
                headers: { ... }, // 服务器返回的响应头信息
                request: { ... }, // 原生的 xhr 对象
                status: 200,  // 服务器响应的HTTP状态码
                statusText: 'OK', // 状态码描述
              }
            + promise 状态为失败
              @1 服务器有返回信息(response 对象存在) 只不过 HTTP 状态码不是以 2 开始的
              reason = {
                config: { ... }, // 发送axios请求设置的配置项
                isAxiosError: true,
                request: XMLHttpRequest实例对象,
                response: 等同于成功获取的 response 对象
                toJSON: function ...,
                message: 'xxx',
                ...
              }
              @2 请求超时 或者 请求失败
                reason = {
                  response: undefined,
                  code: "ECONNABORTED",
                  config: { ... }, // 发送axios请求设置的配置项
                  isAxiosError: true,
                  request: XMLHttpRequest实例对象,
                  toJSON: function ...,
                  message: 'xxx',
                  ...
                }
              + @3 断网了, 特点: 服务器没有任何返回信息
            + 我们可以自定义服务器返回的HTTP状态码为多少是成功, 为多少是失败!!
              axios.get('url', {
                ...,
                // axios的 ValidityStatus 配置项, 就是自定义promise实例状态是成功的条件
                ValidityStatus: status => {
                  return status >= 200 && status < 300   // 默认处理机制
                },
              })
        + 基于 axios 发送请求的方式
          + @1 axios([config]) 或者  axios([url], [config])
          + @2 axios.request([config])
          + @3 axios.get/delete/head/options([url], [config])
          + @4 axios.post/put/patch([url], [data], [config])  => data 基于请求主体传递给服务器的信息
          + @5 let instance = axios.create([config])
               创建的 instance 等同于 axios, 使用起来和axios一样 ...
               instance.get([url], [config])
               ...
        + axios 发送请求时的配置项 config
          + url: 请求的地址   => 发送请求的时候, 但凡没有单独设置url 的, 都需要在配置项中指定
          + baseURL: 请求地址的通用前缀  => 最后发送请求的时候, 是把 baseURL 和 url拼接在一起发送的
            axios.get('/user/list', {
              baseURL: 'http://api.zhufeng.cn',
              ...
            })
            最后发送的请求地址是: 'http://api.zhufeng.cn/user/list'
            特殊情况: 如果url地址本身已经存在了 http 或者 https 等信息, 说明url本身就已经是完整的地址了,
                     baseURL 的值则无需再拼接了
          + transformRequest: (data, headers) => {
              // data => 自己传递的 data
              // headers: 设置的请求头信息{对象}
              return xxxx; 返回值是啥, 最后基于请求主体传递的就是啥
            }
            它只针对于POST请求, 把我们自己传递的data 格式化为指定的格式, 然后再基于请求主体发送给服务器
            axios内部做了一个处理, 根据我们最后处理好的 data 的格式, 自动设置请求头中的Content-Type值(不一定完全准确).
            @1 客户端基于请求主体传递给服务器的数据格式
              + form-data    Content-Type: 'multipart/form-data';
                主要应用于文件上传/表单提交
              + urlencoded   Content-Type: 'application/x-www-form-urlencoded';
                GET系列请求: 是基于URL问号传参把信息传递给服务器的  ?xxx=xxx&xxx=xxx
                xxx=xxx&xxx=xxx 这种字符串就是urlencoded格式字符串
              + raw 泛指, 代指文本格式(普通格式文本字符串; json格式字符串; ...)
                + 普通格式文本字符串  Content-Type: 'text/plain'
                + JSON 格式字符串: Content-Type: 'application/json'
                ...
              + binary  进制格式数据  主要应用于文件上传
            + @2 axios 内部在默认情况下, 如果我们 data 传递的是个普通对象, 而且也没有经过 transformRequest 处理,
                则内部默认会把对象变为JSON格式字符串传递给服务器
          + transformResponse: function (data, headers) {
              // 对发送的 data 进行任意转换处理
              // data: 从服务器拿到的结果, 而且是响应主体信息(服务器响应的主体信息一般都是 JSON 格式字符串)
              return data;
            },
            在我们自己的 .then/catch之前, 对服务器返回的结果进行修改
          + headers: { ... } 自定义请求头信息
          + params: {...}  GET系列请求, 基于 URL 问号参数, 把信息传递给服务器; 我们params一般设置为对象,
            axios 内部会把对象变为 urlencoded 格式拼接到URL的末尾 
            paramsSerializer: function (params) {
              // 默认也是通过 qs.stringify() 对 params 进行处理的
              return Qs.stringify(params, {arrayFormat: 'brackets'}) 
            },
          + data: { ... }  // POST 系列请求, 基于请求主体传递的信息
          + timeout: 12  // 设置超时时间, 写0就是不设置, 单位毫秒
          + withCredentials: false, // 在CORS跨域请求中, 是否允许携带资源凭证
          + responseType: 'json', // responseType 表示浏览器将要响应的数据类型; 
            选项包括: 'arraybuffer', 'document', 'json'(默认值), 'text', 'stream'
          + onUploadProgress: function (progressEvent) {  // onUploadProgress 监听上传的进度
              // 处理原生进度事件
            },
          + onDownloadProgress: function (progressEvent) { // onDownloadProgress 监听下载的进度
              // 处理原生进度事件
            },
          + validateStatus: function (status) {
              return status >= 200 && status < 300; // 默认值
            },
            // 定义服务器但会的状态码是多少, promise 实例是成功的
          + axios 请求的取消, 依赖于 axios.CancelToken 完成
            ....
          + 请求拦截器
            + 请求拦截器: 当 axios 把各方面配置都处理好了, 在即将基于这些配置项服务器发送请求的时候, 触发请求拦截器
            axios.interceptors.request.use(function (config) { 
              // 在发送请求之前做些什么
              // config 存储的是axios处理好的配置, 我们一般在请求拦截器中修改配置
              return config;
            }, function (error) {
              // 对请求错误做些什么
              return Promise.reject(error);
            });
          + 响应拦截器
            + 响应拦截器: 服务器返回结果, axios 已经知道返回的promise实例状态是成功还是失败了, 在自己调用 then/catch
            之前, 先根据promise状态, 把响应拦截器中设置的方法执行
            axios.interceptors.response.use(response => { 
              // 2xx 范围内的状态码都会触发该函数。
              // promise实例是成功的, 执行这个方法: response 存储服务器返回的结果
              return response;
            }, reason => {
              // 超出 2xx 范围的状态码都会触发该函数。
              // promise实例是失败的, 执行这个方法: reason 存储失败的原因
              return Promise.reject(reason);
            });
            响应拦截器中的方法, 相当于自己axios.get('url', params: {...}).then(response => {}).catch(reason => {})之前 
            先 .then(onfulfilled, onrejected) 了
 
    */
    // let xhr = new XMLHttpRequest();
    // xhr.open('GET', './1.json');
    // xhr.setRequestHeader('Content-Type', 'multipart/form-data');
    // xhr.onreadystatechange = function () {
    //   if (xhr.readyState === 4 && xhr.status === 200) {
    //     console.log(xhr.responseText);
    //   }
    // }
    // xhr.send(null);
    // async function getDepartmentList () {
    //   try {
    //     const res = await axios.get('/user/list2', {
    //       ValidityStatus: status => {
    //         return status >= 200 && status < 300   // 以2开头的认为是成功
    //         // return status >= 200 && status < 400  // 以 2 和 3 开头的认为是成功
    //       },
    //       timeout: 1,
    //       params: {
    //         departmentId: 12,
    //         search: ''
    //       }
    //     })
    //     console.log(res)
    //   } catch (error) {
    //     console.dir(error);
    //   }
    // }

    import qs from 'qs'
    import md5 from 'blueimp-md5'
    const source = axios.CancelToken.source();

    async function addDepartment () {
      axios.post(
        '/user/login',
        {
          account: '13213188866',
          password: md5('admin123456')
        },
        {
          transformRequest: (data) => {
            // 如果 data 是纯粹对象才可以调用 qs.stringify() 进行转换
            if (Object.prototype.toString.call(data) === '[object Object]') {
              return qs.stringify(data) // 把对象变为 urlencoded 格式字符串
            }
            return data
          },
          transformResponse: function (data) { // 返回的data 一般是json格式字符串
            console.log(data)
            return JSON.parse(data)
          },
          CancelToken: source.token
        }
      ).then(response => {
        console.log(response)
      }).catch(reason => {
        console.log(reason)
        console.log(reason.message) // 取消原因 =>  '我把请求取消了~~'
      })
      setTimeout(function () {
        source.cancel('我把请求取消了~~')
      })

    }








    // import axios from 'axios'
    // console.dir(axios);
    // const source = axios.CancelToken.source()
    // // 请求接口测试
    // axios.get('/api/news_latest', {
    //   validateStatus: status => (status >= 200 && status > 300),
    //   timeout: 60000,
    //   cancelToken: source.token
    // }).then(response => {
    //   console.log('response', response)
    //   return {
    //     data: response.data,
    //     status: response.status
    //   }
    // }).then(res => {
    //   console.log('res', res) // 想要的主体信息
    // }).catch(reason => {
    //   console.dir(reason)
    //   /* @1 服务器有反馈信息, 但是HTTP状态码不是以2开始的  reason.response.status
    //     reason = {
    //       code: "ERR_BAD_REQUEST",
    //       config: { transitional: {… }, transformRequest: Array(1), transformResponse: Array(1), timeout: 0, adapter: ƒ, … },
    //       message: "Request failed with status code 404",
    //       name: "AxiosError",
    //       request: XMLHttpRequest { onreadystatechange: null, readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, … },
    //     response: { data: '', status: 404, statusText: 'Not Found', headers: {… }, config: {… }, … }
    //     }
    //     @2 请求超时 reason.code == "ECONNABORTED"  reason.response = undefined
    //     @3 请求中断 reason是Cancle的实例对象, reason.message存储中断的原因, 可以基于 axios.isCancel(reason)检测是否为手动中断请求的
    //   */
    //   console.log(axios.isCancel(reason))
    // })
    // // 取消发送请求
    // source.cancel()


    /**
     * axios的二次封装, 就是根据项目需要 后台要求, 把一些 axios 发送请求, 公共的部分进行提取
     * 这样再次基于axios发送请求, 就可以简化一些了
     * 项目中有 100 个接口, 其中 30 个是调用 A服务器; 40个接口调用B服务器; 30个调用C服务器
     * 部分接口和封装的还不太一样
    */
    ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值