当前位置: 首页 > article >正文

ruoyi-vue若依前端是如何防止接口重复请求

防止接口重复请求是为了避免用户在短时间内多次点击同一个按钮,导致后端接口被多次调用,引发数据异常或性能问题。
之前的文章介绍过后端如何防止接口重复请求,这篇文章介绍一下前端如何防止接口重复提交。

按钮禁用

用户点击按钮后立即将按钮设置为禁用状态,待接口返回结果或一段时间后再恢复按钮可用。这样可以有效防止用户在请求未完成时重复点击。

const submitForm = () => {
       if (!buttonDisabled) {
         buttonDisabled = true;
         axios.post('/api/submit', data)
           .then(response => {
             // 请求成功
           })
           .catch(error => {
             // 错误处理
           })
           .finally(() => {
             // 恢复按钮状态
             buttonDisabled = false;
           });
       }
     }

请求拦截器

以下是若依源码:

// request拦截器
service.interceptors.request.use(config => {
  // 是否需要设置 token
  const isToken = (config.headers || {}).isToken === false
  // 是否需要防止数据重复提交
  const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
  if (getToken() && !isToken) {
    config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
  }
  // get请求映射params参数
  if (config.method === 'get' && config.params) {
    let url = config.url + '?' + tansParams(config.params);
    url = url.slice(0, -1);
    config.params = {};
    config.url = url;
  }
  if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
    const requestObj = {
      url: config.url,
      data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
      time: new Date().getTime()
    }
    const sessionObj = cache.session.getJSON('sessionObj')
    if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
      cache.session.setJSON('sessionObj', requestObj)
    } else {
      const s_url = sessionObj.url;                // 请求地址
      const s_data = sessionObj.data;              // 请求数据
      const s_time = sessionObj.time;              // 请求时间
      const interval = 1000;                       // 间隔时间(ms),小于此时间视为重复提交
      if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
        const message = '数据正在处理,请勿重复提交';
        console.warn(`[${s_url}]: ` + message)
        return Promise.reject(new Error(message))
      } else {
        cache.session.setJSON('sessionObj', requestObj)
      }
    }
  }
  return config
}, error => {
    Promise.reject(error)
})

这段代码是一个请求拦截器,用于拦截发送的HTTP请求,并对请求进行一些预处理操作,主要包括Token注入防止重复提交的功能。以下是代码的具体作用:

1. Token设置

const isToken = (config.headers || {}).isToken === false;
if (getToken() && !isToken) {
  config.headers['Authorization'] = 'Bearer ' + getToken(); 
}
  • 作用:检查当前请求是否需要携带Token。通过config.headers.isToken字段决定,若isTokenfalse,表示不需要携带Token,否则会将Authorization头设置为带有Bearer前缀的Token。
  • 逻辑getToken()用于获取存储的Token(比如从cookie或localStorage中),并在请求头中注入Authorization,这样后端能够识别用户身份。

2. GET请求参数处理

if (config.method === 'get' && config.params) {
  let url = config.url + '?' + tansParams(config.params);
  url = url.slice(0, -1);
  config.params = {};
  config.url = url;
}
  • 作用:对于GET请求,将params参数序列化并拼接到URL中。
  • 逻辑:如果请求是GET方法,并且存在params参数,那么它会将这些参数通过tansParams方法(通常是将参数对象转为key=value形式的字符串)拼接到URL后面。最后清空config.params,并将新的URL赋值给config.url

3. 防止重复提交

const isRepeatSubmit = (config.headers || {}).repeatSubmit === false;
if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
  const requestObj = {
    url: config.url,
    data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
    time: new Date().getTime()
  }
  const sessionObj = cache.session.getJSON('sessionObj');
  if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
    cache.session.setJSON('sessionObj', requestObj);
  } else {
    const s_url = sessionObj.url;
    const s_data = sessionObj.data;
    const s_time = sessionObj.time;
    const interval = 1000;
    if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
      const message = '数据正在处理,请勿重复提交';
      console.warn(`[${s_url}]: ` + message);
      return Promise.reject(new Error(message));
    } else {
      cache.session.setJSON('sessionObj', requestObj);
    }
  }
}
  • 作用:用于防止短时间内重复提交相同的POST或PUT请求。
  • 逻辑
    1. 通过检查config.headers.repeatSubmit字段判断是否启用防重复提交(false表示不启用防重)。
    2. 对于需要防止重复提交的请求(POST或PUT方法),会将请求的urldata和当前时间time封装为requestObj对象。
    3. 读取会话缓存中的上一次请求对象(sessionObj),如果不存在,则将当前请求对象保存到会话缓存中。
    4. 如果上一次请求的urldata和当前请求相同,且两次请求时间间隔小于1秒钟(interval = 1000),则视为重复提交,拦截请求并返回错误信息。
    5. 否则,将当前请求对象更新到缓存中,允许请求继续发送。

http://www.kler.cn/a/316643.html

相关文章:

  • 卷积神经网络之Yolo详解
  • CTFHub每日练习
  • 微信小程序中使用离线版阿里云矢量图标
  • 【MySQL】约束
  • 《C++在金融领域的技术革命:高效、安全与创新的融合》
  • 【QT】QSS
  • 计算机前沿技术-人工智能算法-大语言模型-最新论文阅读-2024-09-19
  • 【Linux 20】线程控制
  • Facebook开发者篇 - API拉取广告投放数据对接流程
  • D. Minimize the Difference (Codeforces Round 973 Div. 2)
  • 【人工智能学习笔记】7_智能语音技术基础
  • 【自定义函数】讲解
  • 香港科技大学广州|金融科技学域博士招生宣讲会——武汉大学、华中科技大学
  • 【算法】遗传算法
  • go语言基础入门(一)
  • 安全带检测系统源码分享
  • ArcGIS Pro SDK (十六)公共设施网络 2 网络图
  • MySQL篇(高级字符串函数/正则表达式)(持续更新迭代)
  • Web端云剪辑解决方案,BS架构私有化部署,安全可控
  • 【ARM】A64指令介绍及内存屏障和寄存器
  • 借用连接1-怎么从目标数据源借用连接
  • 【题解-力扣189. 轮转数组(java实现O(1)空间要求)】
  • Python3爬虫教程-HTTP基本原理
  • 数据结构--单链表创建、增删改查功能以及与结构体合用
  • Java 入门指南:JVM(Java虚拟机)—— 双亲委派模型(Parent Delegation Model)
  • 2024短剧系统开发,付费短剧小程序app源码教程,分销功能讲解搭建上线