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全排列的六种算法 具体实现
Jun 29 Javascript
邮箱下拉自动填充选择示例代码附图
Apr 03 Javascript
Javascript中的delete操作符详细介绍
Jun 06 Javascript
Ajax局部更新导致JS事件重复触发问题的解决方法
Oct 14 Javascript
第一次接触神奇的Bootstrap基础排版
Jul 26 Javascript
浅谈jQuery为哪般去掉了浏览器检测
Aug 29 Javascript
javascript自执行函数
Feb 10 Javascript
详解Vue如何支持JSX语法
Nov 10 Javascript
微信小程序文章详情页面实现代码
Sep 10 Javascript
vue二级菜单导航点击选中事件的方法
Sep 12 Javascript
详解Typescript 内置的模块导入兼容方式
May 31 Javascript
vue使用keep-alive实现组件切换时保存原组件数据方法
Oct 30 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 数组教程 定义数组
2009/10/23 PHP
非常实用的php弹出错误警告函数扩展性强
2014/01/17 PHP
PHP的拦截器实例分析
2014/11/03 PHP
DHTML 中的绝对定位
2006/11/26 Javascript
jQuery中将函数赋值给变量的调用方法
2012/03/23 Javascript
解析dom中的children对象数组元素firstChild,lastChild的使用
2013/07/10 Javascript
代码触发js事件(click、change)示例应用
2013/12/13 Javascript
javascript中var的重要性分析
2015/02/11 Javascript
underscore之function_动力节点Java学院整理
2017/07/11 Javascript
Ionic3实现图片瀑布流布局
2017/08/09 Javascript
探索webpack模块及webpack3新特性
2017/09/18 Javascript
Js中使用正则表达式验证输入是否有特殊字符
2018/09/07 Javascript
nodejs aes 加解密实例
2018/10/10 NodeJs
v-slot和slot、slot-scope之间相互替换实例
2020/09/04 Javascript
Python中多线程及程序锁浅析
2015/01/21 Python
在Python的while循环中使用else以及循环嵌套的用法
2015/10/14 Python
Eclipse和PyDev搭建完美Python开发环境教程(Windows篇)
2016/11/16 Python
python 线程的暂停, 恢复, 退出详解及实例
2016/12/06 Python
Django objects.all()、objects.get()与objects.filter()之间的区别介绍
2017/06/12 Python
python select.select模块通信全过程解析
2017/09/20 Python
浅谈配置OpenCV3 + Python3的简易方法(macOS)
2018/04/02 Python
对Python中Iterator和Iterable的区别详解
2018/10/18 Python
python实现简单学生信息管理系统
2020/04/09 Python
详解tensorflow2.x版本无法调用gpu的一种解决方法
2020/05/25 Python
Python绘制词云图之可视化神器pyecharts的方法
2021/02/23 Python
新浪网技术部笔试题
2016/08/26 面试题
DOM和JQuery对象有什么区别
2016/11/11 面试题
保荐人的岗位职责
2013/11/19 职场文书
优秀团员个人事迹材料
2014/01/29 职场文书
网页美工求职信
2014/02/15 职场文书
《小松树和大松树》教学反思
2014/02/20 职场文书
创先争优标语
2014/06/27 职场文书
高中美术教师事迹材料
2014/08/22 职场文书
七一讲话心得体会
2014/09/05 职场文书
演讲开场白和结束语
2015/05/29 职场文书
SQL中的三种去重方法小结
2021/11/01 SQL Server