• 网络模块封装


    网络模块封装

    一、选择什么网络模块

    选择一 :传统的 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
      })
      
  • 相关阅读:
    091122杂记
    20100304我的碎碎念
    写给自己
    开始学习AGG
    找两个数组中的相同元素
    要多写代码了
    [翻译] AGG Reference 之 Basic Renderers(基础渲染器)
    在博客园日志中显示数学公式(旧,ASCIIMathML.js版说明)
    091128日志(博客园博客显示数学公式的方法!)
    与临时对象的斗争(上)
  • 原文地址:https://www.cnblogs.com/downrain/p/11707666.html
Copyright © 2020-2023  润新知