美文网首页axios
axios学习历程(遇到问题持续更新)

axios学习历程(遇到问题持续更新)

作者: Sky_Zh | 来源:发表于2019-04-12 15:18 被阅读0次
    1. axios的作用
    2. axios配置文件
    3. axios在使用中的一些坑

    作用

    axios其实就是vue-resourece的一个更优的基于Promise的解决方案,加上vue-resourece早已停止更新,fetch在配置中又十分的繁琐,这无疑让axios成为我的首选。

    配置文件的说明

    官方文档其实已经说明的很清楚了,在这里记录一下,便于断网的时候查询。

    {
      // `url` 是用于请求的服务器 URL
      url: '/user',
    
      // `method` 是创建请求时使用的方法
      method: 'get', // 默认是 get
    
      // `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
      // 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
      baseURL: 'https://some-domain.com/api/',
    
      // `transformRequest` 允许在向服务器发送前,修改请求数据
      // 只能用在 'PUT', 'POST' 和 'PATCH' 这几个请求方法
      // 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream
      transformRequest: [function (data) {
        // 对 data 进行任意转换处理
    
        return data;
      }],
    
      // `transformResponse` 在传递给 then/catch 前,允许修改响应数据
      transformResponse: [function (data) {
        // 对 data 进行任意转换处理
    
        return data;
      }],
    
      // `headers` 是即将被发送的自定义请求头
      headers: {'X-Requested-With': 'XMLHttpRequest'},
    
      // `params` 是即将与请求一起发送的 URL 参数
      // 必须是一个无格式对象(plain object)或 URLSearchParams 对象
      params: {
        ID: 12345
      },
    
      // `paramsSerializer` 是一个负责 `params` 序列化的函数
      // (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
      paramsSerializer: function(params) {
        return Qs.stringify(params, {arrayFormat: 'brackets'})
      },
    
      // `data` 是作为请求主体被发送的数据
      // 只适用于这些请求方法 'PUT', 'POST', 和 'PATCH'
      // 在没有设置 `transformRequest` 时,必须是以下类型之一:
      // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
      // - 浏览器专属:FormData, File, Blob
      // - Node 专属: Stream
      data: {
        firstName: 'Fred'
      },
    
      // `timeout` 指定请求超时的毫秒数(0 表示无超时时间)
      // 如果请求话费了超过 `timeout` 的时间,请求将被中断
      timeout: 1000,
    
      // `withCredentials` 表示跨域请求时是否需要使用凭证
      withCredentials: false, // 默认的
    
      // `adapter` 允许自定义处理请求,以使测试更轻松
      // 返回一个 promise 并应用一个有效的响应 (查阅 [response docs](#response-api)).
      adapter: function (config) {
        /* ... */
      },
    
      // `auth` 表示应该使用 HTTP 基础验证,并提供凭据
      // 这将设置一个 `Authorization` 头,覆写掉现有的任意使用 `headers` 设置的自定义 `Authorization`头
      auth: {
        username: 'janedoe',
        password: 's00pers3cret'
      },
    
      // `responseType` 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
      responseType: 'json', // 默认的
    
      // `xsrfCookieName` 是用作 xsrf token 的值的cookie的名称
      xsrfCookieName: 'XSRF-TOKEN', // default
    
      // `xsrfHeaderName` 是承载 xsrf token 的值的 HTTP 头的名称
      xsrfHeaderName: 'X-XSRF-TOKEN', // 默认的
    
      // `onUploadProgress` 允许为上传处理进度事件
      onUploadProgress: function (progressEvent) {
        // 对原生进度事件的处理
      },
    
      // `onDownloadProgress` 允许为下载处理进度事件
      onDownloadProgress: function (progressEvent) {
        // 对原生进度事件的处理
      },
    
      // `maxContentLength` 定义允许的响应内容的最大尺寸
      maxContentLength: 2000,
    
      // `validateStatus` 定义对于给定的HTTP 响应状态码是 resolve 或 reject  promise 。如果 `validateStatus` 返回 `true` (或者设置为 `null` 或 `undefined`),promise 将被 resolve; 否则,promise 将被 rejecte
      validateStatus: function (status) {
        return status >= 200 && status < 300; // 默认的
      },
    
      // `maxRedirects` 定义在 node.js 中 follow 的最大重定向数目
      // 如果设置为0,将不会 follow 任何重定向
      maxRedirects: 5, // 默认的
    
      // `httpAgent` 和 `httpsAgent` 分别在 node.js 中用于定义在执行 http 和 https 时使用的自定义代理。允许像这样配置选项:
      // `keepAlive` 默认没有启用
      httpAgent: new http.Agent({ keepAlive: true }),
      httpsAgent: new https.Agent({ keepAlive: true }),
    
      // 'proxy' 定义代理服务器的主机名称和端口
      // `auth` 表示 HTTP 基础验证应当用于连接代理,并提供凭据
      // 这将会设置一个 `Proxy-Authorization` 头,覆写掉已有的通过使用 `header` 设置的自定义 `Proxy-Authorization` 头。
      proxy: {
        host: '127.0.0.1',
        port: 9000,
        auth: : {
          username: 'mikeymike',
          password: 'rapunz3l'
        }
      },
    
      // `cancelToken` 指定用于取消请求的 cancel token
      // (查看后面的 Cancellation 这节了解更多)
      cancelToken: new CancelToken(function (cancel) {
      })
    }
    // 响应结构
    // 某个请求的响应包含以下信息
    
    {
      // `data` 由服务器提供的响应
      data: {},
    
      // `status` 来自服务器响应的 HTTP 状态码
      status: 200,
    
      // `statusText` 来自服务器响应的 HTTP 状态信息
      statusText: 'OK',
    
      // `headers` 服务器响应的头
      headers: {},
    
      // `config` 是为请求提供的配置信息
      config: {}
    }
    

    其实这里的话是要 axios(config) 这样里面去的想一想这么多的配置文件要一股脑都塞进去,确实看起来是非常的不雅而且整个主代码会变得乱七八糟,没错,刚开始学习的我真的这样做了,后期几乎是完全没法维护的,后来我通过学习花裤衩大大的代码,才知道,这些东西是可以封装起来的,大概分出来两个文件。

    首先是axios的配置文件(需要自己创建哦我个人是命名为request.js并且丢在src的utils文件夹中自己建的)

    import axios from 'axios'
    // axios配置信息
    axios.defaults.withCredentials = true
    const service = axios.create({
      baseURL: process.env.BASE_API, // api 的 前缀url
      timeout: 5000, // 请求超时
    })
    // 数据发送前的拦截器
    service.interceptors.request.use(
      config => {
        return config
      },
      error => {
        Promise.reject(error)
      }
    )
    // 数据接受时的拦截器
    service.interceptors.response.use((response) => {
      return response
    }, (err) => {
      switch (err.response.status) {
        case 500:
          
          break;
        case 429:
          
          break;
        default:
          
      }
    
    })
    
    export default service
    
    
    1. 首先是这个配置文件,在axios.create这个方法中,有baseURL和timeout这两个配置,前者指向的是webpack的开发环境和生产环境,这个如果有自己配置的话,就在里面加一个baseURL即可,如果还不清楚的话,建议通过console来查看具体位置;再下面就是有两个拦截器,一个是数据发送前,一个是数据接受时,这两个拦截器用处很大,我这么配置之后,基本一目了然,在下面的res拦截器中,可以捕获到http错误码,可以通过判断和后端的错误码来给予用户最人性化的提示。
    2. 而在数据发送前的这个拦截器则可以统一配置 header等这一系列的东西从而避免在主代码中去重新设置这些东西,比如使用qs去转换需要发送的数据对吧,很方便的。

    请求地址配置文件(同样是需要自己创建我个人是新建了一个目录api,然后把它放入新加的js文件中)

    // 在此处导入之前配置的service
    import request from 'request'
    export default {
        // 内容为请求的函数,例如:
        post(data) {
        return request({
          url: "",
          method: "post",
          data
        })
      },
        get(params) {
        return request({
          url: "",
          method: "get",
          params
        })
      },
    }
    

    这里的请求配置文件就很明了了,导入之后使用 export default将其中的函数全部暴露出去方便调用,而函数内则是这样的一个结构,在函数内部配置一个 url,method,data,为什么要将这些配置分离出来配置而不是在之前的配置文件中使用,因为服务端提供的接口方式多是多样,可以是get,post,put,dele其中的任意一个,而url则是前面相同部分的服务器地址后面的接口地址那部分,听起来是不是有点绕?举个栗子:现在有两个接口,https://skyserver.com/get_listhttps://skyserver.com/get_list 那么我就可以设baseURL为 https://skyserver.com,而这里的url则是 /get_list 或者是 /get_list ,明白了吗?每一个接口我们只需要更改后面的接口名和请求方式就好了。

    如何去使用?

    emm,其实使用方法有很多,我个人推荐是去main.js文件中去引入,例如我引入之后的名字是api那么我就可以使用这行代码Vue.prototype.$api = api意思为将这个挂载到vue的原型中去,这样的好处就是我们可以直接使用this.$api.get()的方式进行调用,由于axios本身就是一个基于Promise的项目,其实就可以直接使用async and await的形式来进行调用,借助webpack的一部分功能让自己的代码本体变得不再那么冗余。

    踩过的坑

    1. axios本身不会发送cookie,需要你自己加上axios.defaults.withCredentials = true这句代码才会发送cookie,但是会存在跨域问题,在这里由于我只使用了nodejs作为后端所以只举例nodejs如何解决这个跨域问题的:

    首先我使用的是的是express框架,不过影响不大,毕竟koa和其他的都是差不多的原理。话不多说先上代码:

    // 我们可以直接获取访问服务器的来源直接赋值过去,虽然方便,但是要知道本身这个是防御XSS攻击,这么设置之后的风险阅读者应该要须知。
    let origin = req.header.origin
    //访问控制允许来源,有人会问为什么这里不是一个'*'呢,因为在启用了cookie之后,是不允许使用通配符的,所以在当需要发送cookie的场景中
    res.header('Access-Control-Allow-Origin', origin);
    //访问控制允许报头 X-Requested-With: xhr请求
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept,X-Token");
    //访问控制允许方法
    res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
    // 它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。
    res.header("Access-Control-Allow-Credentials",true);
    //自定义头信息,表示服务端用nodejs,其实你也可以发送其他的2333虽然意义不明
    res.header('X-Powered-By', 'nodejs');
    // 定义发送的数据格式
    res.header('Content-Type', 'application/json;charset=utf-8');
    
    

    这里出现的弊端,想必一眼就看出来了对吗?这里允许了所有来访者的url,但是事实上我们并不能这样允许,因为这样是有安全问题的!so,做个判断不就好啦:

    // 这里规定一个白名单,允许哪些域名访问,是一个数组
    let whitList = ['','']
    // 这里则使用的是es6的语法,检查该变量是否存在于数组中
    // 和es5中的 `indexOf()` 有异曲同工之妙,但是它返回的是一个布尔值,除了不能够定位元素的位置,但是用在此处很棒不是么~
    if(whitList.includes(origin)){
        // 这里是上面的那段代码
    }
    

    1. axios是基于es6语法的,你可能会遇到 Promise is not function 的问题,通常出现在老旧浏览器上,可以通过bable来进行转换。下图是其浏览器的支持。

    Chrome Firefox Safari Opera Edge IE
    Latest ✔ Latest ✔ Latest ✔ Latest ✔ Latest ✔ 11 ✔
    1. 它拦截接收报错的信息是在 err.response 中,而不是直接的err就可以获取到,这一点是很坑的,一直以来我都以为是在err中,导致始终无法捕捉到http状态值以及报错信息,其实官方文档也有说明,如果我不是那么的星际也不会犯这种低级错误

    相关文章

      网友评论

        本文标题:axios学习历程(遇到问题持续更新)

        本文链接:https://www.haomeiwen.com/subject/vppcwqtx.html