【Vue项目回顾】网络模块的封装

选择什么网络模块

选择一: 传统的Ajax是基于XMLHttpRequest(XHR)

为什么不用它呢?

  • 非常好解释, 配置和调用方式等非常混乱.
  • 编码起来看起来就非常蛋疼.
  • 所以真实开发中很少直接使用, 而是使用jQuery-Ajax

选择二: 在前面的学习中, 我们经常会使用jQuery-Ajax

  • 相对于传统的Ajax非常好用.

为什么不选择它呢?

  • 首先, 我们先明确一点: 在Vue的整个开发中都是不需要使用jQuery了.
  • 那么, 就意味着为了方便我们进行一个网络请求, 特意引用一个jQuery, 你觉得合理吗?
    jQuery的代码1w+行.Vue的代码才1w+行.完全没有必要为了用网络请求就引用这个重量级的框架.

选择三: 官方在Vue1.x的时候, 推出了Vue-resource.
Vue-resource的体积相对于jQuery小很多.
另外Vue-resource是官方推出的.

为什么不选择它呢?

  • 在Vue2.0退出后, Vue作者就在GitHub的Issues中说明了去掉vue-resource, 并且以后也不会再更新.那么意味着以后vue-reource不再支持新的版本时, 也不会再继续更新和维护.对以后的项目开发和维护都存在很大的隐患.

选择四: 在说明不再继续更新和维护vue-resource的同时, 作者还推荐了一个框架: axios

  • axios有非常多的优点, 并且用起来也非常方便.

Jsonp封装

在前端开发中, 我们一种常见的网络请求方式就是JSONP

  • 使用JSONP最主要的原因往往是为了解决跨域访问的问题.

JSONP的原理是什么呢?

  • JSONP的核心在于通过< script>标签的src来帮助我们请求数据.
  • 原因是我们的项目部署在domain1.com服务器上时, 是不能直接访问domain2.com服务器上的资料的.
  • 这个时候, 我们利用

【Vue项目回顾】网络模块的封装_第1张图片

JSONP如何封装呢?
【Vue项目回顾】网络模块的封装_第2张图片

【Vue项目回顾】网络模块的封装_第3张图片

为什么选择axios?

功能特点:

  • 在浏览器中发送 XMLHttpRequests 请求
  • 在 node.js 中发送 http请求
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求和响应数据等等

axiox请求方式

支持多种请求方式:

  • axios(config)
  • axios.request(config)
  • axios.get(url[, config])
  • axios.delete(url[, config])
  • axios.head(url[, config])
  • axios.post(url[, data[, config]])
  • axios.put(url[, data[, config]])
  • axios.patch(url[, data[, config]])

axios的最基本的使用

需求:在App.vue中发送网络请求,并且从服务器请求过来对应的数据,展示在页面上
因为我们要使用axios这个框架,所以我们先要安装这个框架

npm install axios --save

【Vue项目回顾】网络模块的封装_第4张图片
我们将项目启动起来,可见这个Object确实是在17行打印出来的
【Vue项目回顾】网络模块的封装_第5张图片

axios({
  url:'http://123.207.32.32:8000/home/multidata',
  methods:'get'
}).then(res=>{
  console.log(res);
})

这个请求方式默认的就是get请求,当然我们也可以直接设置请求方式,此时还是将其设置为get请求,最终的效果没有什么变化。(给的这个接口是不支持post的请求的)

axios({
  url:'http://123.207.32.32:8000/home/data',
  params:{
    type:'pop',
    page:1
  }
}).then(res=>{
  console.log(res);
})

到时候内部会做一个拼接(上面的请求是专门针对get请求的参数拼接)

axios发送并发请求

有时候, 我们可能需求同时发送两个请求

  • 使用axios.all, 可以放入多个请求的数组.
  • axios.all([]) 返回的结果是一个数组,使用 axios.spread 可将数组 [res1,res2] 展开为 res1, res2

在开发中,有的时候需要发送两个请求,并且这两个请求最终都达到以后再做一个功能(发送多个并发请求,同时到达以后再做进一步的处理)

//2.axios发送并发请求
axios.all([axios(),axios()]).then()

实例:

//2.axios发送并发请求
axios.all([axios({
  url:'http://123.207.32.32:8000/home/multidata'
}),axios({
  url:'http://123.207.32.32:8000/home/data',
  params:{
    type:'sell',
    page:3
  }
})]).then(results=>{
  console.log(results);
})

【Vue项目回顾】网络模块的封装_第6张图片
可以再对结果做一个延展

axios.all([axios({
  url:'http://123.207.32.32:8000/home/multidata'
}),axios({
  url:'http://123.207.32.32:8000/home/data',
  params:{
    type:'sell',
    page:3
  }
})]).then(axios.spread((res1,res2)=>{
  console.log(res1);
  console.log(res2);
  }
))

【Vue项目回顾】网络模块的封装_第7张图片

axios全局配置

在上面的示例中, 我们的BaseURL是固定的

  • 事实上, 在开发中可能很多参数都是固定的.
  • 这个时候我们可以进行一些抽取, 也可以利用axios的全局配置
axios.defaults.baseURL='http://123.207.32.32:8000',
axios.defaults.timeout=5000

axios.all([axios({
  url:'/home/multidata'
}),axios({
  url:'/home/data',
  params:{
    type:'sell',
    page:3
  }
})]).then(axios.spread((res1,res2)=>{
  console.log(res1);
  console.log(res2);
  }
))

结果
在这里插入图片描述

常见的配置选项

请求地址

  • url: ‘/user’,
    请求类型
  • method: ‘get’,
    请根路径
  • baseURL: ‘http://www.mt.com/api’,
    请求前的数据处理
  • transformRequest:[function(data){}],
    请求后的数据处理
  • transformResponse: [function(data){}],
    自定义的请求头
  • headers:{‘x-Requested-With’:‘XMLHttpRequest’},
    URL查询对象
  • params:{ id: 12 },
    查询对象序列化函数
  • paramsSerializer: function(params){ }
    request body
  • data: { key: ‘aa’},
    超时设置s
  • timeout: 1000,
    跨域是否带Token
  • withCredentials: false,
    自定义请求处理
  • adapter: function(resolve, reject, config){},
    身份验证信息
  • auth: { uname: ‘’, pwd: ‘12’},
    响应的数据格式 json / blob /document /arraybuffer / text / stream
  • responseType: ‘json’,

axios的实例

为什么要创建axios的实例呢?

  • 当我们从axios模块中导入对象时, 使用的实例是默认的实例.
  • 当给该实例设置一些默认配置时, 这些配置就被固定下来了.
  • 但是后续开发中, 某些配置可能会不太一样.
  • 比如某些请求需要使用特定的baseURL或者timeout或者content-Type等.
  • 这个时候, 我们就可以创建新的实例, 并且传入属于该实例的配置信息.
// 创建对应的axios的实例
const instance=axios.create()
// 4.创建对应的axios的实例
const instance1=axios.create({
  baseURL:'http://123.207.32.32:8000',
  timeout:5000
})

instance1({
  url:'/home/multidata'
}).then(res=>{
  console.log(res);
})

instance1({
  url:'/home/data',
  params:{
    type:'pop',
    page:1
  }
}).then(res=>{
  console.log(res);
})

const instance2=axios.create({
  baseURL:'http://222.111.33.33:8000',
  timeout:10000,
})
...

结果如下:
【Vue项目回顾】网络模块的封装_第8张图片

axios封装

一般都是新建一个network文件夹,只要涉及网络层的封装,我们都把它封装到这个文件夹中。在文件夹中新建request.js文件
【Vue项目回顾】网络模块的封装_第9张图片
但是我们不能在这里接收结果,我们需要把这个结果给调用者传出去,而且这里也有可能会出现异常,我们也需要把这个异常传出去。那我们怎么将这些东西回调出去呢?
办法有很多:
第1种方式:我们可以通过success和failure把得到的结果回调出去
【Vue项目回顾】网络模块的封装_第10张图片
此时如果使用的话,我们
【Vue项目回顾】网络模块的封装_第11张图片

此时res这个箭头函数就是我们网络模块中的success
跑一下项目,结果出错,原因是baseURL中多加了’/home/multidata’,删除掉,我们可以得到结果
【Vue项目回顾】网络模块的封装_第12张图片
第2种方式:
在request.js中只要一个参数

export function request(config){
  //1.创建一个axios实例
  const instance=axios.create({
    baseURL:'http://123.207.32.32:8000',
    timeout:5000
  })

  instance(config.baseConfig)
    .then(res=>{
    // console.log(res);
   config.success(res)
  }).catch(err=>{
    // console.log(err);
    config.failure(err)
  })
}

那么使用的时候则为:
【Vue项目回顾】网络模块的封装_第13张图片
reques里面一整个都是config的内容,具体在用的时候,再做解析
【Vue项目回顾】网络模块的封装_第14张图片
从config中拿到baseConfig传入到instance里面,然后从config中取出传入的success做一个回调

最终的方案为:

【Vue项目回顾】网络模块的封装_第15张图片
那么调用呢?
【Vue项目回顾】网络模块的封装_第16张图片
最终我们还可以进行改进
【Vue项目回顾】网络模块的封装_第17张图片
调用还是按照上述方法进行调用

如何使用拦截器?

axios提供了拦截器,用于我们在发送每次请求或者得到相应后,进行对应的处理。
它既提供了请求成功的拦截,又提供了请求失败的拦截;响应成功的时候可以进行拦截,响应失败的时候也可以进行拦截
【Vue项目回顾】网络模块的封装_第18张图片
结果如下:

【Vue项目回顾】网络模块的封装_第19张图片
也就是只打印了config,没有打印err里面的内容。发送请求发送出去了,代表我这次请求起码发送是成功的。接着看那个err,是main.js中的84行打印的
【Vue项目回顾】网络模块的封装_第20张图片
可见我们这次信息发送出去了,但是没有拿到最终的结果。
原因是在这一步把我们的信息拦截了
【Vue项目回顾】网络模块的封装_第21张图片

所以我们还需要把这个config原封不动的给他返回出去(相当于拦截了config,但是没有给它返回,最终还是拿不到这个config,内部发送请求的时候,它里面所有的信息都拿不到了)

【Vue项目回顾】网络模块的封装_第22张图片
我们再跑一遍项目结果如下:
【Vue项目回顾】网络模块的封装_第23张图片
这就是请求拦截,一般会在请求拦截中做什么事情呢?

  1. 比如config中的一些信息不符合服务器的要求
  2. 比如每次发送网络请求时,都希望在界面中显示一个请求的图标
  3. 某些网络请求(比如录(token),必须携带一些特殊的信息

响应拦截:
【Vue项目回顾】网络模块的封装_第24张图片
结果为:
![在这里插入图片描述](https://img-blog.csdnimg.cn/30bcd3cdf5a648f9a95939220e54c0d2.png
但是我们也不能在request.js里面接收数据,所以我们
【Vue项目回顾】网络模块的封装_第25张图片
然后在main.js中
【Vue项目回顾】网络模块的封装_第26张图片

最终的一个效果如下:
【Vue项目回顾】网络模块的封装_第27张图片

你可能感兴趣的:(vue,vue.js,javascript,前端)