vue+ts下对axios的封装实现


Posted in Javascript onFebruary 18, 2020

虽然vue中axios的使用已经十分方便,但是实际我们的日常操作中可能为了接口的规则一致,来创建一个统一管理的全局方法达到简化操作.而且在实际接口对接中,我们大多都需要对请求和响应进行拦截来进行token以及回调状态码的处理.那么我基于自己的需求简单分装了一下.(之前很少接触vue,主要用的ng和react,这次新项目想用vue来弄,熟悉一下vue的一些新特性和方法,有啥不对的,欢迎大家批评指正)
前提: 熟悉前端ts, node等等.

1. 安装axios

npm install axios -D

2. 拦截器及全局方法编写

一个http.ts文件进行自己http逻辑的封装,为了代码分离,我同时创建interceptors.ts文件进行拦截器逻辑,放在一起也行.

interceptors.ts(拦截器,进行请求和响应拦截并进行部分逻辑处理)

import axios from 'axios';
  import {message} from 'ant-design-vue'; // 这是我引入的antd的组件库,为了方便弹出吐司
  
  export class Interceptors {
    public instance: any;
  
    constructor() {
      // 创建axios实例
      this.instance = axios.create({timeout: 1000 * 12});
      // 初始化拦截器
      this.initInterceptors();
    }
    
    // 为了让http.ts中获取初始化好的axios实例
    public getInterceptors() {
      return this.instance;
    }
  
  
    // 初始化拦截器
    public initInterceptors() {
      // 设置post请求头
      this.instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
      /**
      * 请求拦截器
      * 每次请求前,如果存在token则在请求头中携带token
      */
      this.instance.interceptors.request.use(
        (config) => {
          // 登录流程控制中,根据本地是否存在token判断用户的登录情况
          // 但是即使token存在,也有可能token是过期的,所以在每次的请求头中携带token
          // 后台根据携带的token判断用户的登录情况,并返回给我们对应的状态码
          if (config.headers.isJwt) {
            const token = localStorage.getItem('id_token');
            if (token) {
              config.headers.Authorization = 'Bearer ' + token;
            }
          }
          return config;
        },
        (error) => {
          console.log(error);
        },
      );
  
  
      // 响应拦截器
      this.instance.interceptors.response.use(
        // 请求成功
        (res) => {
          if (res.headers.authorization) {
            localStorage.setItem('id_token', res.headers.authorization);
          } else {
            if (res.data && res.data.token) {
              localStorage.setItem('id_token', res.data.token);
            }
          }
  
          if (res.status === 200) {
            return Promise.resolve(res.data);
          } else {
            this.errorHandle(res);
            return Promise.reject(res.data);
          }
        },
        // 请求失败
        (error) => {
          const {response} = error;
          if (response) {
            // 请求已发出,但是不在2xx的范围
            this.errorHandle(response);
            return Promise.reject(response.data);
          } else {
            // 处理断网的情况
            // eg:请求超时或断网时,更新state的network状态
            // network状态在app.vue中控制着一个全局的断网提示组件的显示隐藏
            // 关于断网组件中的刷新重新获取数据,会在断网组件中说明
            message.warn('网络连接异常,请稍后再试!');
          }
        });
    }
  
  
    /**
    * http握手错误
    * @param res 响应回调,根据不同响应进行不同操作
    */
    private errorHandle(res: any) {
      // 状态码判断
      switch (res.status) {
        case 401:
          break;
        case 403:
          break;
        case 404:
          message.warn('请求的资源不存在');
          break;
        default:
          message.warn('连接错误');
      }
    }
  }

http.ts(http封装,自己根据实际情况处理)

/**
 * @author keiferju
 * @time  2019-08-29 12:57
 * @title  http请求封装
 * @desc
 *
 */
import {Interceptors} from '@/service/interceptors';
import {message, Modal} from 'ant-design-vue';  // 弹吐司
import router from '../router';

export class HttpService {
  public axios: any;
  public modal: any;

  constructor() {
      // 获取axios实例
    this.axios = new Interceptors().getInterceptors();
  }


  /**
   * get请求
   * @param params 参数
   * @param jwt  是否token校验
   * @param modulename  模块
   * @param operation   接口
   * @param flag     标记
   * @param verson    版本,默认1.0.0
   * @param service   服务,默认services
   */
  public getData(params: object, jwt: boolean, modulename: string, operation: string,
          flag: string, verson = '1.0.0', service = 'services') {

    const url = service + '/' + verson + '/' + modulename + '/' + operation;
    const body = {
      parameter: {
        data: params,
        tag: flag,
      },
    };

    return new Promise((resolve, reject) => {
      this.axios.get(url, {
        params: body,
        headers: {isJwt: jwt},
      }).then((res) => {
        this.resultHandle(res, resolve);
      }).catch((err) => {
        reject(err.message);
      });
    });

  }


  /**
   * post请求
   * @param params 参数
   * @param jwt  是否token校验
   * @param modulename  模块
   * @param operation   接口
   * @param flag     标记
   * @param verson    版本,默认1.0.0
   * @param service   服务,默认services
   */
  public postData(params: object, jwt: boolean, modulename: string, operation: string,
          flag: string, verson = '1.0.0', service = 'services') {
    const url = service + '/' + verson + '/' + modulename + '/' + operation;
    const body = {
      data: params,
      tag: flag,
    };
    return new Promise((resolve, reject) => {
      this.axios.post(url, body, {
        headers: {isJwt: jwt},
      }).then((res) => {
        this.resultHandle(res, resolve);
      }).catch((err) => {
        reject(err.message);
      });
    });

  }


  /**
   *
   * @param res
   * @param resolve
   */
  public resultHandle(res: any, resolve) {
    if (res.status > 0) {
      resolve(res.data);
    } else {
      this.errorHandle(res);
    }
  }


  /**
   * 服务端状态处理,例如中断性异常,退出异常等等(与拦截器http握手状态注意区分,一般都能分清楚吧)
   * @param res
   */
  public errorHandle(res: any) {
    message.warn(res.msg); // 统一谈服务端提示,我们提示统一由服务端提供
    // 状态码判断
    switch (res.status) {
      case -102: 
         break;
      case -152:
        break;
      default:
      // console.log(other);
    }
  }

}

3. 挂载

我们定义好拦截器,那么就得把他挂载全局,能让我们方便使用.

main.ts

import Vue from 'vue';
import App from './App.vue';
import HighchartsVue from 'highcharts-vue';

Vue.config.productionTip = false;

Vue.prototype.$httpService = new HttpService(); // 挂载服务

new Vue({
  router,
  render: (h) => h(App),
}).$mount('#app');

4. ts桥连(也不知道怎么称呼,自己从ng时就一直这么称呼)

行完上一步一定会发现报错啊,$httpService是个啥,不存在啊,这是因为ts的特性导致.

main.ts的同级目录创建一个xx.d.ts文件.

import {HttpService} from './service/http';
  
declare module 'vue/types/vue' {
  interface Vue {
    $httpService: HttpService;
  }
}

5. 使用

在其它组件中使用,直接用this调用,不用再去引用,但是小心在某个this指向变了的回调中使用时找不到,至于怎么怎么解决应该都懂.

this.$httpService.postData({}, true, 'execute', 'xxx', 'tag').then((result) => {
       // doing      
}, (error) => {
   console.log(error);
});

最后:这是在ts下的封装,js的话更简单点,甚至应该会更简单点(会少一些步骤,网上教程应该很多).挂载http工具的方式平时也适合我们定义全局工具类或者服务.

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript document.referrer 用法
Apr 30 Javascript
JS获取dom 对象 ajax操作 读写cookie函数
Nov 18 Javascript
在JavaScript中重写jQuery对象的方法实例教程
Aug 25 Javascript
jQuery中detach()方法用法实例
Dec 25 Javascript
web前端开发upload上传头像js示例代码
Oct 22 Javascript
Vue 实用分页paging实例代码
Apr 12 Javascript
jquery实现图片轮播器
May 23 jQuery
JavaScript求一组数的最小公倍数和最大公约数常用算法详解【面向对象,回归迭代和循环】
May 07 Javascript
浅谈vue首屏加载优化
Jun 28 Javascript
vee-validate vue 2.0自定义表单验证的实例
Aug 28 Javascript
微信小程序如何调用图片接口API并居中显示
Jun 29 Javascript
js实现抽奖功能
Nov 24 Javascript
ES6中Promise的使用方法实例总结
Feb 18 #Javascript
React中获取数据的3种方法及优缺点
Feb 18 #Javascript
JavaScript canvas绘制渐变颜色的矩形
Feb 18 #Javascript
JavaScript canvas绘制折线图
Feb 18 #Javascript
node+multer实现图片上传的示例代码
Feb 18 #Javascript
JavaScript canvas绘制圆弧与圆形
Feb 18 #Javascript
javascript中的with语句学习笔记及用法
Feb 17 #Javascript
You might like
新版PHP将向Java靠拢
2006/10/09 PHP
PHP的简易冒泡法代码分享
2012/08/28 PHP
执行、获取远程代码返回:file_get_contents 超时处理的问题详解
2013/06/25 PHP
php的memcache类分享(memcache队列)
2014/03/26 PHP
PHP封装XML和JSON格式数据接口操作示例
2019/03/06 PHP
yii框架结合charjs统计上一年与当前年数据的方法示例
2020/04/04 PHP
特殊字符、常规符号及其代码对照表
2006/06/26 Javascript
探讨JavaScript中声明全局变量三种方式的异同
2013/12/03 Javascript
一个html5播放视频的video控件只支持android的默认格式mp4和3gp
2014/05/08 Javascript
JQuery CheckBox(复选框)操作方法汇总
2015/04/15 Javascript
js实现3d悬浮效果
2017/02/16 Javascript
nodejs模块学习之connect解析
2017/07/05 NodeJs
JavaScript模拟文件拖选框样式v1.0的实例
2017/08/04 Javascript
Vue.js搭建移动端购物车界面
2020/06/28 Javascript
bootstrap动态调用select下拉框的实例代码
2018/08/09 Javascript
微信小程序顶部导航栏滑动tab效果
2019/01/28 Javascript
JS实现简单的抽奖转盘效果示例
2019/02/16 Javascript
js/jquery遍历对象和数组的方法分析【forEach,map与each方法】
2019/02/27 jQuery
通过实例解析JavaScript for in及for of区别
2020/06/15 Javascript
JavaScript 获取滚动条位置并将页面滑动到锚点
2021/02/08 Javascript
Python中使用tarfile压缩、解压tar归档文件示例
2015/04/05 Python
python实现爬虫统计学校BBS男女比例之数据处理(三)
2015/12/31 Python
深入解析Python中的__builtins__内建对象
2016/06/21 Python
Python标准模块--ContextManager上下文管理器的具体用法
2017/11/27 Python
python开发准备工作之配置虚拟环境(非常重要)
2019/02/11 Python
python中的句柄操作的方法示例
2019/06/20 Python
Python中zip()函数的解释和可视化(实例详解)
2020/02/16 Python
利用css3径向渐变做一张优惠券的示例
2018/03/22 HTML / CSS
Canvas引入跨域的图片导致toDataURL()报错的问题的解决
2018/09/19 HTML / CSS
社会保险接收函
2014/01/12 职场文书
四年级学生评语大全
2014/04/21 职场文书
我的中国梦演讲稿300字
2014/08/19 职场文书
作风建设年活动总结
2014/08/27 职场文书
党务工作者主要事迹材料
2015/11/03 职场文书
学习计划是什么
2019/04/30 职场文书
25张裸眼3D图片,带你重温童年的记忆,感受3D的魅力
2022/02/06 杂记