网络模块封装

网络模块封装

一、选择什么网络模块

选择一 :传统的 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-resource 的同时,作者还推荐了一个框架: axios
  • 为什么用它?
    • axios 有非常多的优点 ,并且用起来也非常的方便。

二、jsonp

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

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

  • JSONP 的原理是什么呢?

    • JSONP 的核心在于通过 script 标签的 src 来帮助我们请求数据。
    • 原因是我们的项目部署在domain1.com 服务器上时,是不能直接访问 domain2.com 服务器上的资料的。
    • 这个时候,我们利用 script 标签的src 来帮助我们去服务器 请求 到数据,将数据当做一个 JavaScript的函数䣂执行,并且执行的过程中传入我们需要的 json。
    • 所有,封装 jsonp 的核心就在于我们 监听 window上的 jsonp 进行回调的名称。
  • JSONP 如何封装呢?

    • 我们一起自己来封装一个出来 JSONP的代码吧。

      let count = 1
      export default function originPJSONP(option) {
          // 1. 从传入的 option 中提取 URL
          const url = option.url;
          
          // 2. 在body中添加 script 标签
          const body = document.getElementsByTagName('body')[0];
          const script = document.createElement('script');
          
          // 3. 内部生成一个 不重复的 callback
          const callback = 'jsonp' + count++;
          
          // 4. 监听 window 上的 jsonp 的调用
          return new Promise((resolve, roject) => {
              try {
                  window[callback] = function (result) {
                      body.removeChild(script);
                      resolve(result)
                  }
                  const params = handleParam(option.data);
                  body.appendChild(script)
              } catch (e) {
                  body.removeChild(script)
                  reject(e)
              }
          })
      }
      
      function handleParam(data) {
          let url = ''
          for (let key in data) {
              let value = data[key] !== undefined ? data[key] : ''
              url += `&${key} = ${encodeURIComponent(value)}` 
          }
          return url
      }
      

三、为什么选择 axios

1、功能特点:
  • 在浏览器中发送 XMLHttpRequests 请求
  • 在 node.js 中发送 http 请求
  • 支持 Promise API
  • 拦截请求和 响应
  • 转换 请求 和 响应数据
  • 等等
2、补充 : axios 名称的由来、个人理解

axios : Ajax i/o system

3、axios 请求方式
  • 支持多种请求方式

    • 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]])
  • 如何发送请求呢?

    • 案例:发送 get 请求

      import axios from 'axios'
      
      export default {
          name: 'app',
          created() {
              // 提问: 为什么没有跨域问题
              // 1. 没有请求参数
              axios.get("http://www.liulongbin.top:3005/api/getlunbo")
              .then(res => {
                  console.log(res);
              }).catch(err => {
                  console.log(err);
              })
              
              // 2. 有请求参数
              axios.get('http://123.207.32.32:8000/home/data', {params: { type: 'sell', page: 1}})
              .then(res => {
                  console.log(res);
              }).catch(err => {
                  console.log(err);
              })
          }
      }
      
  • 发送并发请求

    • 有时候,我们可以需要同时发送两个请求

      • 使用 axios.all , 可以放入多个请求的数组,

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

        // 2. axios 发送并发请求
        axios
          .all([
            axios({
              url: "http://www.liulongbin.top:3005/api/getlunbo"
            }),
            axios({
              url: "http://123.207.32.32:8000/home/data",
              params: {
                type: "sell",
                page: 3
              }
            })
          ])
          .then(res => {
            axios.spread((res1, res2) => {
              console.log(res1);
              console.log(res2);
            });
          });
        
  • 全局配置

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

      • 事实上,在并发中肯很多参数都是固定的

      • 这个时候我们可以进行一些抽取,也可以利用axios的全局配置

        axios.defaults.baseURL = 'http://www.liulongbin.top:3005/api'
        axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlenconded';
        
        // 提取全局配置
        axios.defaults.baseURL = "http://www.liulongbin.top:3005/api"
        
        axios
          .all([
            axios({
              url: "/getlunbo"
            }),
            axios({
              // url: "http://123.207.32.32:8000/home/data",
              url: "/getnewslist",
            })
          ])
          .then(res => {
            axios.spread((res1, res2) => {
              console.log(res1);
              console.log(res2);
            });
          });
        
4、常见的配置选项
  • 请求地址

    • url: '/user',
  • 请求类型

    • method: 'get',
  • 请求根路径

  • 请求前的数据处理

    • transformRequest: [function(data) {}],
  • 自定义的请求头

    • headers: {'x-Requested-With':'XMLHttpRequest'},
  • URL查询对象

    • params:{id: 12},
5、axios 的实例
  • 为什么要创建 axios 的实例呢

    • 当我们从 axios 模块中导入对象时,使用的实例是默认的实例

    • 当给该实例设置一些默认配置时,这些配置就被固定下来了。

    • 但是后续开发中,某些配置可能会不太一样

    • 比如某些请求需要使用特定的 baseURL 或者 timeout 或者 content-Type 等

    • 这个时候,我们就可以创建新的实例,并且传入属于该实例的配置信息

      // 创建新的实例
      const axiosInstance = axios.create({
          baseURL: 'http://123.207.32.32:8000',
          timeout: 5000,
          headers: {}
      })
      
    
    ```json
    // 发送网络请求
axiosInstance({
        url: '/category',
        method: 'get'
    }).then(res => {
        console.log(res)
    }).catch(err) => {
        console.log(err)
    }

6、axios 封装 (使用 Promise 进行封装)
import originAxios from 'axios'

export default function axios(option) {
    return new Promise((reslove, reject) => {
        // 1. 创建 axios 的实例
        const instance =originAxios.create({
            baseURL: 'api',
            timeout: 5000
        })
        
        // 2. 传入对象进行网络请求
        instance(option).then(res => {
            resolve(res)
        }).catch(err => {
            reject(err)
        })
    })
}
7、如何使用拦截器
  • axios 提供了拦截器,用于我们在发送每次请求或者得到响应后,进行对应的处理。

  • 如何使用拦截

    // 配置请求和响应拦截
    instance.interceptors.request.use(config => {
        // 请求拦截成功
        console.log('来到了 request 拦截 success中')
        return config
    }, err => {
        // 请求拦截失败
        console.log('request 拦截 failure 中')
    })
    
    instance.interceptors.response.use(response => {
        // 响应拦截成功
        console.log('来到了 response 拦截 success 中')
        return response.data
    }, err => {
        // 响应拦截失败
        console.log('来到了 response 拦截 failure 中')
        return err
    })
    
posted @ 2019-10-20 15:12  管希民  阅读(391)  评论(0编辑  收藏  举报