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采用数组实现tab菜单切换效果
Dec 12 Javascript
利用jQuery的deferred对象实现异步按顺序加载JS文件
Mar 17 Javascript
一个简单的动态加载js和css的jquery代码
Sep 01 Javascript
基于jquery的手风琴图片展示效果实现方法
Dec 16 Javascript
jQuery学习笔记之jQuery中的$
Jan 19 Javascript
零基础轻松学JavaScript闭包
Dec 30 Javascript
JavaScript限定范围拖拽及自定义滚动条应用(3)
May 17 Javascript
原生JS实现图片无缝滚动方法(附带封装的运动框架)
Oct 01 Javascript
通过js控制时间,一秒一秒自己动的实例
Oct 25 Javascript
基于js 字符串indexof与search方法的区别(详解)
Dec 04 Javascript
在Vue methods中调用filters里的过滤器实例
Aug 30 Javascript
Vue安装浏览器开发工具的步骤详解
May 12 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+MySQL的聊天室设计
2006/10/09 PHP
php木马攻击防御之道
2008/03/24 PHP
php下关于Cannot use a scalar value as an array的解决办法
2010/08/08 PHP
比较简单的百度网盘文件直链PHP代码
2013/03/24 PHP
ajax返回值中有回车换行、空格的解决方法分享
2013/10/24 PHP
php使用正则表达式进行字符串搜索的方法
2015/03/23 PHP
PHP编写学校网站上新生注册登陆程序的实例分享
2016/03/21 PHP
jQuery checkbox全选/取消全选实现代码
2009/11/14 Javascript
Javascript倒计时代码
2010/08/12 Javascript
JavaScript全局函数使用简单说明
2011/03/11 Javascript
Extjs显示从数据库取出时间转换JSON后的出现问题
2012/11/20 Javascript
jquery监听div内容的变化具体实现思路
2013/11/04 Javascript
处理文本部分内容的TextRange对象应用实例
2014/07/29 Javascript
JavaScript极简入门教程(二):对象和函数
2014/10/25 Javascript
浅析Javascript中bind()方法的使用与实现
2016/05/30 Javascript
JavaScript实现定时页面跳转功能示例
2017/02/14 Javascript
小程序登录/注册页面设计的实现代码
2019/05/24 Javascript
js实现图片粘贴到网页
2019/12/06 Javascript
vue动画—通过钩子函数实现半场动画操作
2020/08/09 Javascript
用python登录Dr.com思路以及代码分享
2014/06/25 Python
python检测远程udp端口是否打开的方法
2015/03/14 Python
python验证码识别实例代码
2018/02/03 Python
django mysql数据库及图片上传接口详解
2019/07/18 Python
Python解压 rar、zip、tar文件的方法
2019/11/19 Python
如何在python开发工具PyCharm中搭建QtPy环境(教程详解)
2020/02/04 Python
基于django micro搭建网站实现加水印功能
2020/05/22 Python
python 实现控制鼠标键盘
2020/11/27 Python
HTML5 画布canvas使用方法
2016/03/18 HTML / CSS
详解Canvas实用库Fabric.js使用手册
2019/01/07 HTML / CSS
html5自定义video标签的海报与播放按钮功能
2019/12/04 HTML / CSS
销售人员获奖感言
2014/02/05 职场文书
计算机毕业生自荐信
2014/06/12 职场文书
反邪教标语
2014/06/23 职场文书
2014最新党员批评与自我批评材料
2014/09/24 职场文书
大二学生自我检讨书
2014/10/23 职场文书
撤回我也能看到!教你用Python制作微信防撤回脚本
2021/06/11 Python