vue2/3 axios 请求重试、取消请求、loading 串行并行等(分享)

这篇具有很好参考价值的文章主要介绍了vue2/3 axios 请求重试、取消请求、loading 串行并行等(分享)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

基础版,添加 loading

在请求响应拦截器里面添加 loading,这样就不需要给每一个请求添加 loading 了
这些代码都是 vue2 项目的,vue3 也通用,改一下 loading 和 message 就好了(主要是 element 的区别)
我这里最后没有合并代码,有的配置不适合写在一起,看自己项目的需要

import axios from 'axios';
import { Loading, Message } from 'element-ui';

const instance = axios.create({
  baseURL: 'http://localhost:5500',
  timeout: 30000,
});

let loadingInstance = null;
// 添加请求拦截器
instance.interceptors.request.use(
  (config) => {
    loadingInstance = Loading.service({
      fullscreen: true,
      text: '加载中...',
      background: "black",
    });
    return config;
  },
  // 断网走这里
  (error) => {
    Message.error('请求错误:' + error.message);
    return Promise.reject(error);
  },
);

// 添加响应拦截器
instance.interceptors.response.use(
  ({ data }) => {
    loadingInstance.close();
    return data;
  },
  // !== 2xx 走这里
  (error) => {
    loadingInstance.close();
    return Promise.reject(error.response);
  },
);

export default instance

响应状态码配置

响应状态码配置,更好的给用户提示,这里只设计到响应,就只写了响应拦截

// 根据规范添加配置
const statusOption = [
  {
    code: "200",
    state: "success",
    description: "请求(或处理)成功",
  },
  {
    code: "400",
    state: "ParameterError",
    description: "请求参数不完整或不正确",
  },
  {
    code: "401",
    state: "Unauthorized",
    description: "访问请求未授权! 当前 SESSION 失效, 请重新登陆",
  },
  {
    code: "403",
    state: "Forbidden",
    description: "您无权进行此操作,请求执行已拒绝",
  },
  {
    code: "404",
    state: "NotFound",
    description: "找不到与请求匹配的 HTTP 资源",
  },
  {
    code: "405",
    state: "HttpMehtodError",
    description: "HTTP请求类型不合法",
  },
  {
    code: "406",
    state: "HttpRequestError",
    description: "HTTP请求不合法,请求参数可能被篡改",
  },
  {
    code: "407",
    state: "URLExpireError",
    description: "该URL已经失效",
  },
  {
    code: "500",
    state: "Error",
    description: "内部请求出错",
  },
];

// 添加响应拦截器
instance.interceptors.response.use(
  ({ data }) => {
    loadingInstance.close();
    // 这里是请求成功的内部状态码
    // 这个要和后端约定,我这里就默认除了 200 都有问题
    // 这样就不用在请求接口出错的时候一个个 message 了
    if (data.status !== 200) {
      Message.error(data.message);
      return Promise.reject(data);
    }
    return Promise.resolve(data);
  },
  (error) => {
    let status = error.response.status;
    if (status < 400) {
      Message.warning(error.response.statusText);
    } else {
      let err = statusOption.find((item) => item.code == status);
      Message.error(err ? err.description : "响应出错请联系管理员!");
    }
    loadingInstance.close();
    return Promise.reject(error.response);
  }
);

loading 串行、并行

串行 loading 闪屏、并行 loading 提前关闭

  • 串行的情况是请求之间的依赖,请求 A 完成后立即开始请求 B,这样会导致 loading 闪屏
  • 并行是两个请求同时请求,请求 A 的时间为 5s,请求 B 的时间为 3s,因为 loading 都是同一个实例,会导致请求 B 时提前关闭 loading,关闭两秒后又请求到了新的数据
import axios from "axios";
import { Loading, Message } from 'element-ui';

const instance = axios.create({
  baseURL: "http://localhost:5500",
  timeout: 30000,
});

// 处理并行
let loadingCount = 0;

// 处理串行
let loadingTimer = null;

function loadingClose() {
  loadingCount--;
  if (!loadingCount) {
    // 延迟等待是否还有下一个请求
    loadingTimer = setTimeout(() => {
      loadingInstance.close();
      loadingTimer = null;
    }, 300);
  }
}

function loadingOpen() {
  loadingCount++;
  // 如果有请求需要清除关闭
  if (loadingTimer) {
    clearTimeout(loadingTimer);
    loadingTimer = null;
  }
  loadingInstance = Loading.service({
    fullscreen: true,
    text: "加载中...",
    background: "black",
  });
}

let loadingInstance = null;
// 添加请求拦截器
instance.interceptors.request.use(
  (config) => {
    loadingOpen();
    return config;
  },
  (error) => {
    Message.error("请求错误:" + error.message);
    return Promise.reject(error);
  }
);

// 添加响应拦截器
instance.interceptors.response.use(
  ({ data }) => {
    loadingClose();
    return data;
  },
  (error) => {
    loadingClose();
    return Promise.reject(error.response);
  }
);

export default instance;

请求挂起

延迟请求发送
我这里的应用场景是 token,当我发现当前请求没有 token 时,先挂起当前请求然后获取 token,在添加上

import axios from "axios";
import { Loading, Message } from 'element-ui';

const instance = axios.create({
  baseURL: "http://localhost:5500",
  timeout: 30000,
});

// 获取 token 的方法,这里的请求不能使用封装的,不然请求一直没有 token 就会一直挂起
async function passParamsGetToken() {}

let loadingInstance = null;
// 添加请求拦截器
instance.interceptors.request.use(
  // 这种用 async/await 也可以,更易读一些,原理都是等待请求的发送
  (config) => {
    if (!config.headers.Authorization) {
      // 请求挂起
      return new Promise(async (resolve, reject) => {
        let token = await passParamsGetToken();
        // 为当前请求添加 token
        config.headers.Authorization = token;
        // 为实例添加 token,这样下一个请求也会存在token
        instance.defaults.headers.common["Authorization"] = token;

        loadingInstance = Loading.service({
          fullscreen: true,
          text: "加载中...",
          background: "black",
        });
        resolve(config);
      });
    } else {
      loadingInstance = Loading.service({
        fullscreen: true,
        text: "加载中...",
        background: "black",
      });
      return config;
    }
  },
  (error) => {
    Message.error("请求错误:" + error.message);
    return Promise.reject(error);
  }
);

// 添加响应拦截器
instance.interceptors.response.use(
  ({ data }) => {
    loadingInstance.close();
    return data;
  },
  (error) => {
    loadingInstance.close();
    return Promise.reject(error.response);
  }
);

export default instance;

取消请求

重复请求需要取消,取消请求会走响应拦截器的 error,会和请求重试有冲突

  • 取消请求不是真正意义上的取消,请求已经发送,后端接收到了,只是前端不在响应了
  • 使用表单类的操作,取消请求没用,顶多是获取列表的时候,前端少处理一次操作
import axios from "axios";
import { Loading, Message } from 'element-ui';

const requestMap = new Map();

function setRequestMap(config) {
  requestMap.set(JSON.stringify(config), config);
}

function deleteRequestMap(config) {
  let xLConfig = JSON.stringify(config);
  let hasConfig = null;
  if ((hasConfig = requestMap.get(xLConfig))) {
    // 请求完成后在取消,不影响
    hasConfig.controller.abort();
    requestMap.delete(xLConfig);
  }
}

// 设置控制器,需要先设置控制器,这样添加删除后的序列化字符才可以匹配
function setAbortController(config) {
  const controller = new AbortController();
  config.controller = controller;
  config.signal = controller.signal;
}

const instance = axios.create({
  baseURL: "http://localhost:5500",
  timeout: 30000,
});

let loadingInstance = null;
// 添加请求拦截器
instance.interceptors.request.use(
  (config) => {
    setAbortController(config);
    deleteRequestMap(config);
    setRequestMap(config);

    loadingInstance = Loading.service({
      fullscreen: true,
      text: "加载中...",
      background: "black",
    });
    return config;
  },
  (error) => {
    Message.error("请求错误:" + error.message);
    return Promise.reject(error);
  }
);

// 添加响应拦截器
instance.interceptors.response.use(
  (response) => {
    deleteRequestMap(response.config);
    loadingInstance.close();
    return response.data;
  },
  (error) => {
    // 重复请求的取消,表示后面肯定有请求,则不需要关闭 loading
    if (axios.isCancel(error)) {
      // console.log("Request canceled", 123123);
      // 其他异常的处理
    } else {
      deleteRequestMap(error.config);
      loadingInstance.close();
    }
    return Promise.reject(error.response);
  }
);

export default instance;

请求重试

请求失败需要重试文章来源地址https://www.toymoban.com/news/detail-496976.html

// utils/reuqest.js 中
import axios from "axios";
import { Loading, Message } from 'element-ui';

const instance = axios.create({
  baseURL: "http://localhost:5500",
  timeout: 30000,
  retry: 3, // 最大重试次数为 3
  retryDelay: 1000, // 重试时的延迟时间为 1 秒
});

let loadingInstance = null;
// 添加请求拦截器
instance.interceptors.request.use(
  (config) => {
    loadingInstance = Loading.service({
      fullscreen: true,
      text: config.retryCount ? "请求重试中..." : "加载中...", // 重试后改变 text 显示
      background: "black",
    });
    return config;
  },
  (error) => {
    Message.error("请求错误:" + error.message);
    return Promise.reject(error);
  }
);

// 添加响应拦截器
instance.interceptors.response.use(
  ({ data }) => {
    loadingInstance.close();
    return data;
  },
  (error) => {
    loadingInstance.close();
    const config = error.config;
    // 没有重试的请求直接抛出
    if (!config || !config.retry) {
      return Promise.reject(error);
    }

	// 超过重试次数抛出
    config.retryCount = config.retryCount || 0;
    if (config.retryCount >= config.retry) {
      // 因为每次请求的实例对象都不一样,所以为当前实例添加 retryCount,不会影响其他实例
      return Promise.reject(error);
    }

	// 请求重试
    config.retryCount += 1;
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve(instance(config));
      }, config.retryDelay);
    });
  }
);

export default instance;

到了这里,关于vue2/3 axios 请求重试、取消请求、loading 串行并行等(分享)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • vue2前端使用axios发起post请求,后端(springboot)拿不到值解决办法

    axios封装-我常用的请求头参数  application/json; charset=utf-8 页面登录请求-post 网络请求正常传入参数 后端代码,查看控制台发现都为null,没取到值。 1.尝试将前端post请求改成get,其他都不用变 发现正常取到值,打印输出正常。前端页面正常跳转。 2.后端设置为post请求,前端a

    2024年02月02日
    浏览(49)
  • axios使用axiosSource.cancel取消请求后怎么恢复请求,axios取消请求和恢复请求实现

    在前端做大文件分片上传,或者其它中断请求时,需要暂停或重新请求,比如这里大文件上传时,可能会需要暂停、继续上传,如下GIF演示: 这里不详细说文件上传的处理和切片细节,后续有时间在出一篇,大文件上传,切片上传、断点续传、秒传等😀。 不扯远了,紧接本

    2024年02月12日
    浏览(43)
  • axios-retry插件-axios请求失败自动重试

    axios-retry 对外导出 axiosRetry() 方法: 通过对 axios 单例添加“拦截器”,来扩展实现自动重试网络请求功能。 备注:  除非  shouldResetTimeout 被设置, 这个插件 将请求超时解释为全局值, 不是针对每一个请求,二是全局的设置 Name Type Default Description retries Number 3 The number of times t

    2024年02月10日
    浏览(77)
  • Vue2 axios 发请求报400错误 “Error: Request failed with status code 400“

    最近在做一个项目,后端写了一个登录接口,postman可以正常请求。但我axios发请求出现400错误 \\\"Error: Request failed with status code 400\\\" 请求: 错误:  我研究了两天,查了无数资料,最后和朋友一起找到解决方法 原因:后端没跟我说需要什么格式的数据,我以为是默认的json,后来

    2024年02月11日
    浏览(65)
  • 【Vue框架】Vue2中axios发送请求—安装axios、配置全局域名、传递参数、axios原理之Promise(什么是Promise、使用原因、基本使用、相关API、async与await使用)

    官网: https://www.axios-http.cn/ 1.1.1 安装axios库 安装 axios 通信库: npm install axios -S 1.1.2 在全局中引入axios库 全局在main.js中引入axios: import axios from \\\'axios\\\' 1.1.3 挂在原型对象 Vue.prototype.$axios = axios; 将 axios 挂载到Vue原型对象中,实现数据共享,节约内存空间。 此时在任何页面都可

    2024年02月05日
    浏览(50)
  • axios中取消请求的使用

    1.全局定义一个axios控制器变量 axiosController 2.配置axios 对象signal 3.创建setAxiosController函数 导出变量、函数 每次调用axiosController.abort()方法后就需要重新调用setAxiosController; axios官网 取消请求 mdn官网 AbortController在fetch中的使用

    2024年02月07日
    浏览(46)
  • axios取消请求CancelToken的用法

    axios中取消请求情况分为1:取消该请求之后的相同请求;2:取消该请求之前的相同请求 ##取消该请求之后的相同请求: 在使用 axios 发送请求时,如果在短时间内连续发送同一个请求,可能会出现请求结果混乱或重复响应的问题。为了避免这种情况,我们可以使用 axios 的取消

    2024年02月14日
    浏览(39)
  • Axios中使用CancelToken取消请求

    CancelToken 是一个用于取消请求的机制。它允许在请求还未完成时,通过取消请求来终止请求的发送。这在需要在某些情况下中止正在进行的请求时非常有用,比如文件上传时取消上传等。 以下是使用 CancelToken 的一般步骤: 首先,导入 Axios 库和相关的依赖: 创建一个 Cancel

    2024年02月10日
    浏览(48)
  • Axios使用CancelToken取消重复请求

    处理重复请求:没有响应完成的请求,再去请求一个相同的请求,会把之前的请求取消掉 新增一个 cancelRequest.js 文件 request.js

    2024年02月12日
    浏览(45)
  • axios如何取消请求,其原理是什么?

    原文合集地址如下,有需要的朋友可以关注 本文地址 axios 可以通过创建一个 CancelToken 来取消一个请求,基本原理是: 创建一个 CancelToken 的实例,它有一个 executor 函数,可以通过调用 executor 参数中的 cancel 函数来取消请求。 在 axios 请求配置中指定 cancelToken 属性,将 CancelToken 实例

    2024年02月12日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包