你有封装过 axios 吗?主要是封装哪些方面?如何中断 axios 请求?

  • 一、封装过哪些方面?
    • 1.1 http 封装
    • 1.2 api 封装
      • 1.2.1 总 api 接口的映射
      • 1.2.2 建立一个 get_url.js,用于获取域名地址,实现环境切换可配置
      • 1.2.3 单个模块接口定义
      • 1.2.4 断网处理
    • 1.3 将 api 挂载到全局
    • 1.4 中断 axios 请求

一、封装过哪些方面?


基本逻辑如上,主要是对请求封装和 api 接口封装。

1.1 http 封装

http 封装,其实就是实例化一个 axios 对象,并对其进行一些配置:

  1. 设置请求超时

  2. post 头设置

  3. 请求拦截

  4. 响应拦截

  5. 重复请求取消(这里涉及到了如何取消请求)

  6. 错误处理

  7. 断网处理

  8. 工具函数

    import axios from 'axios'
    import router from '../router'
    import store from '../store/index'
    import { Toast } from 'vant'// 提示函数
    const tip = msg => {Toast({message: msg,duration: 1000,forbidClick: true})
    }
    // 跳转登录页,携带当前页面路由,登录后返回当前页面
    const toLogin = () => {router.replace({path: '/login',query: {redirect: router.currentRoute.fullPath}})
    }
    // 错误处理
    const errorHandle = (status, other) => {switch (status) {// 未登录case 401:toLogin();break;// 403 token过期,清除token并跳转登录页case 403:tip('登录过期,请重新登录');localStorage.removeItem('token');store.commit(loginSuccess, null);setTimeout(() => {toLogin();}, 1000);break;//请求不存在case 404:tip('请求资源不存在');break;default:console.log(other)}
    }// 用于存储目前状态为pending的请求标识信息
    let pendingRequest = [];// 取消请求-请求拦截中的处理
    const CancelToken = config => {// 区别请求的唯一标识,这里用方法名+请求路径const requestMark = `${config.method} ${config.url}`;// 找当前请求的标识是否存在pendingRequest中,即是否重复请求了const markIndex = pendingRequest.findIndex(item => {return item.name === requestMark;});// 存在,即重复了if (markIndex > -1) {// 取消上个重复的请求pendingRequest[markIndex].cancel();// 删掉在pendingRequest中的请求标识pendingRequest.splice(markIndex, 1);}// (重新)新建针对这次请求的axios的cancelToken标识const CancelToken = axios.CancelToken;const source = CancelToken.source();config.cancelToken = source.token;// 设置自定义配置requestMark项,主要用于响应拦截中config.requestMark = requestMark;// 记录本次请求的标识pendingRequest.push({name: requestMark,cancel: source.cancel,});return config;
    };// 取消请求-响应拦截中的处理
    const CancelTokenResponse = config => {// 根据请求拦截里设置的requestMark配置来寻找对应pendingRequest里对应的请求标识const markIndex = pendingRequest.findIndex(item => {return item.name === config.requestMark;});// 找到了就删除该标识markIndex > -1 && pendingRequest.splice(markIndex, 1);
    }// 创建axios实例
    var instance = axios.create({timeout: 1000 * 12
    })// 设置post请求头
    instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';// 请求拦截器
    instance.interceptors.request.use(config => {config = CancelToken(config);const token = store.state.token;token && (config.headers.Authorization = token);return config;},error => Promise.reject(error);
    )
    // 响应拦截器
    instance.interceptors.response.use(res => {// 请求结束就从pendingRequest删除请求标志CancelTokenResponse(res.config);return res.status === 200 ? Promise.resolve(res) : Promise.reject(res);},error => {const { response } = error;// 请求已经发出,返回结果不在2xx的范围if (response) {CancelTokenResponse(response.config);errorHandle(response.status, response.data.message);return Promise.reject(response);} else {// 断网情况,刷新重新获取数据if (!window.navigator.onLine) {store.commit('changeNetwork', false);} else {return Promise.reject(error);}}}
    )export default instance;
    

1.2 api 封装

api 封装,主要是用于单个模块所需要的接口进行管理。其中包括了

  1. 总 api 接口的映射
  2. 环境变量的切换
  3. 本地 mock 的功能
  4. 单个模块的接口列表

1.2.1 总 api 接口的映射

  • api 中定义一个 index.js ,用于所有模块接口的管理

    //api接口统一出口
    import user from "./user";
    import productList from "./product";
    //...export { user, productList };
    

1.2.2 建立一个 get_url.js,用于获取域名地址,实现环境切换可配置

  • get_url.js

    import config from "@/config";
    import urlMap from "@/config/urlMap";//api控制接口类型,1为远程接口,0为mock接口
    export default function getUrl(url, api = 1) {return api === 0 ? urlMap[url] : config.apiDomain + url;
    }
    
  • 新建一个配置文件夹 config,其中的 index 文件用于切换环境,urlMap 用于本地 mock 地址的映射

    //config/index.js
    /*** 配置编译环境和线上环境之间的切换* 默认三套可以增添*/let apiDomain;
    switch (process.env.NODE_ENV) {case "dev":apiDomain = "https://www.dev.com";break;case "prod":apiDomain = "https://www.prod.com";break;case "test":apiDomain = "https://www.test.com";break;
    }
    export { apiDomain };
    
    //urlMap.js
    /*** 远程接口地址和本地mock地址映射表* key:接口地址* value:本地地址*/
    const mockBaseUrl = "http://rap2api.taobao.org/app/mock";
    export default {"/user/login": mockBaseUrl + "/223948/login","/user/info": mockBaseUrl + "/223948/info","/user/logout": mockBaseUrl + "/223948/logout",
    };
    

1.2.3 单个模块接口定义

//产品列表接口
import axios from "@/http";
import getUrl from "@/api/get_url";const product = {// 新闻列表productList() {return axios({url: getUrl("/topics"),method: "get",});},// 新闻详情,演示productDetail(id, params) {return axios({url: getUrl(`/topic/${id}`),params: params,method: "get",});},// post提交login(data) {return axios({url: getUrl(`${base.sq}/accesstoken`),method: "post",data,});},//...更多接口
};export default product;

1.2.4 断网处理

  1. http 封装中,当断网时,会对 Vue 的网络状态进行更新

  2. 在 App.vue 中,根据网络情况,判断是否需要加载断网组件

  3. 全局定义一个断网组件,实现跳转重新获取页面的操作

    <!-- App.vue -->
    <template><div id="app"><div v-if="!network"><h3>我没网了</h3><div @click="onRefresh">刷新</div></div><router-view /></div>
    </template><script>import { mapState } from "vuex";export default {name: "App",computed: {...mapState(["network"]),},methods: {// 通过跳转一个空页面再返回的方式来实现刷新当前页面数据的目的onRefresh() {this.$router.replace("/refresh");},},};
    </script>
    

    http.js 中断网的时候,会更新 vue 中的 network 的状态。此时,根据 network 的状态来判断是否需要加载这个断网组件。当点击刷新的时候,我们通过跳转 refresh 页面,然后立即返回的方式,来实现重新获取数据的操作。因此,我们需要新建一个 refresh.vue 页面,并在其 beforeRouteEnter 钩子中再返回当前页面。

    // refresh.vue
    beforeRouteEnter (to, from, next) {next(vm => {vm.$router.replace(from.fullPath)})
    }
    

1.3 将 api 挂载到全局

//main.js
import Vue from "vue";
import App from "./App";
import router from "./router"; // 导入路由文件
import store from "./store"; // 导入vuex文件
import api from "./api"; // 导入api接口Vue.prototype.$api = api; // 将api挂载到vue的原型上

1.4 中断 axios 请求

上面避免重复请求中,就使用到了 cancel token 取消请求,使用 CancelToken 工厂方法创建 cancel token

const CancelToken = axios.CancelToken;
const source = CancelToken.source();axios.get("/user/12345", {cancelToken: source.token,
}).catch(function (thrown) {if (axios.isCancel(thrown)) {console.log("Request canceled", thrown.message);} else {// 处理错误}
});axios.post("/user/12345",{name: "new name",},{cancelToken: source.token,}
);// 取消请求(message 参数是可选的)
source.cancel("Operation canceled by the user.");

【Day01】你有封装过 axios 吗?主要是封装哪些方面?如何中断 axios 请求?相关推荐

  1. axios 上传文件 封装_axios使用及封装

    axios跨域及封装 1.安装 npm install axios --save 2.main.js引用 import axios from 'axios'; 3.axios基本用法 function ...

  2. axios的二次封装与async,await的配合使用?

    前言:前些日子读文章,说是vue3.0会在明年下半年正式推出,改动的地方好像也不少,比如说vue3.x的代码库将会用typescript编写,并提供改进的 TypeScript 支持.变化还是很快的, ...

  3. axios如何二次封装

    axios二次封装的五种方法 为什么要封装 axios 的 API 很友好,你完全可以很轻松地在项目中直接使用. 不过随着项目规模增大,如果每发起一次HTTP请求,就要把这些比如设置超时时间.设置请求 ...

  4. axios进行二次封装

     Web开发中,我们最常用的HTTP库就是Axios了,它的底层基于Ajax进行封装,在浏览器端和服务端都可以使用.如果大家对一些API不是很熟悉可以参考官方地址,或者中文社区.    为什么要对ax ...

  5. Vue——axios的二次封装

    文章目录 一.请求和传递参数 1.get 请求 2.post 请求 3.axios 请求配置 二.axios 的二次封装 1.配置拦截器 2.发送请求 三.API 的解耦 1.配置文件对应的请求 2. ...

  6. axios的使用和封装(九)

    前言 axios 是一个基于 Promise 用于浏览器和 nodejs 的 HTTP 客户端,本质上也是对原生XHR的封装,只不过它是Promise的实现版本,符合最新的ES规范.本章我们将介绍并演 ...

  7. axios介绍以及对axios进行二次封装

    目录 一.axios基础 1.什么是axios? 2.axios的安装 3.axios常用配置项 4.axios和ajax的区别 二.使用axios发送请求 1. 发送get无参请求 2. 发送get ...

  8. axios的二次封装(详解)

    一.首先让我们了解一下为什么要对axios进行二次封装? 1,代码封装,重用性高,减少代码量,减低维护难度. 2,统一处理一些常规的问题一劳永逸,如http错误. 3,拦截请求和响应,提前对数据进行处 ...

  9. axios 上传文件 封装_axios封装和传参

    axios封装和传参 1.开发环境 vue+typescript 2.电脑系统 windows10专业版 3.在开发的过程中,我们会经常使用到 axios进行数据的交互,下面我来说一下,axios封装 ...

最新文章

  1. 使用Spring Data Redis操作Redis(集群版)
  2. 使用keepalived加lvs做负载均衡,访问后端的服务器,2分钟后超时,需要重新登录...
  3. oracle访问远程db2,如何在DB2与Oracle之间实现远程拷贝(二)
  4. 九度 1474:矩阵幂(二分法)
  5. spark的外排:AppendOnlyMap与ExternalAppendOnlyMap
  6. 使用python中的networkx来生成一个图
  7. 将ini文件内容读出
  8. WebViewJavascriptBridge 进行js 与native通信。
  9. Python爬虫番外篇之关于登录
  10. WebSocket消息推送(实现进行聊天)和WebSocket简介
  11. mysql必知必会样例表_《SQL必知必会》笔记1-样例表说明及建表语句
  12. 中山大学羽毛球场馆自动订场(Python+selenium+百度aip)
  13. 如何衡量和分配广告渠道?
  14. 坦克世界未能连接至更新服务器,坦克世界连接到更新服务器失败,小猪教您怎么解决坦克世界连接到更新服务器...
  15. 中国人民银行清算总中心CDA业务数据分析师培训正式开课
  16. 没有购买域名和服务器,怎么搭建网站?(一)
  17. 工作总结与个人职业经历
  18. 小程序学习与实践(一)
  19. 黑马就业班(02.JavaWeb+项目实战\18.LinuxNginx)
  20. QrCodeUtil--二维码工具类

热门文章

  1. lua——赢三张牌型处理相关算法(中)——牌型判定
  2. 阿里云 Centos 7 PHP7环境配置 LNMP
  3. Logistics模型预测银行贷款违约
  4. C/C++—— #include“stdafx.h”详解
  5. 【Pandas】dataframe 设置完全显示所有列
  6. MxNet 迁移学习实现深度学习分类
  7. Linux—目录文件属性和权限管理详解
  8. JVM——Java内存模型(JMM)
  9. css标签的三种显示模式
  10. 云题库进入其它章节的办法 0925