前端代码连续点击多次按钮,导致数据提交多次,导致后端幂等,解决方案(全局 每次前端请求设置Loading加载效果,请求完成后,关闭Loading加载)

实战,实现幂等的8种方案! 幂等是一个数学与计算机科学概念。。比如求绝对值的函数,就是幂等的,。计算机科学中,幂等表示一次和多次请求某一个资源应该具有同样的副作用,或者说,多次请求所产生的影响与一次请求执行的影响效果相同。 阅读详情
AI摘要

本文探讨了编程中的幂等概念,特别是在前端开发中的应用。通过介绍如何处理多次请求以避免幂等问题,文章详细讲解了如何使用Element UI的loading效果,以及结合axios的请求和响应拦截器实现全局loading加载。在处理多个请求时,文章提出了改进的loading效果,确保所有请求完成后再关闭loading,从而提高用户体验。

1、文章开篇:什么是幂等?

幂等(idempotent、idempotence)是一个数学与计算机学概念,常见于抽象代数中。

在编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。幂等函数,或幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数。这些函数不会影响系统状态,也不用担心重复执行会对系统造成改变。例如,“setTrue()”函数就是一个幂等函数,无论多次执行,其结果都是一样的.更复杂的操作幂等保证是利用唯一交易号(流水号)实现。

简单说:在编程中就是发多次请求,但是请求都是一样的,结果是一样的。

比如说,向数据库中新增1条数据,其实简单的来说就是设一个点击按钮,这个都没有问题,但是假如说我们向后端传输的数据有很多,页面并没有说及时得到反映,这个时候我们应该如何去处理?

其实很多前端程序员的通病就是写代码的时候不考虑代码的复用以及组件的扩展性,包括我个人也是一样,这样就会导致后期要维护的时候Bug有很多,同样代码的耦合性也会同样很高,当然这样肯定是不好的。

好的言归正传说会 幂等这个问题,如果是增加一条数据,那么前端页面肯定是会去触发一个事件,但是如果我们手抖不小心点击了两次呢?是不是就会向后端请求两次数据呢?

答案当然会,其实这就是幂等问题,包括像删除,假如说我要根据一条数据的id去删除数据,我第一次点击按钮请求时,那么数据库后端已经根据这个id去对数据库中的数据进行了操作,但是如果我在请求的过程中又点击了一次,其实这个时候如果后端再去根据这个id去更改变更数据库。仔细考虑一下,会出现什么问题呢?

当然言归正传,后端自然会有后端的处理方案,悲观锁,乐观锁,本地锁等等。

当然今天我们主要讲的就是前端如何去处理,尽量去减少后端的幂等?

1、前端怎么样去做处理?

在这里插入图片描述
看到这个转圈圈是不是很熟悉?
没错就是新增一个loading效果,每次当我们向后端发送请求时,新增一个转圈圈效果那不就好了么?

在这里的话我们就不讲js原生了,因为其实loading的原理就是创建一个隐藏的遮罩层,当用户点击button的时候,就把这个遮罩层展示出来,当数据已经从服务器返还回来时,就让这个遮罩层隐藏。

当然在现在基本上我们都是用ui框架的年代里,loading肯定是各个ui库都是已经给我们封装好了的,那么我们今天就来详细的介绍一下关于element的loading加载效果

2、效果

首先我们可以看一下官网给我们的案例

<template>
  <el-button
    type="primary"
    @click="openFullScreen1"
    v-loading.fullscreen.lock="fullscreenLoading">
    指令方式
  </el-button>
  <el-button
    type="primary"
    @click="openFullScreen2">
    服务方式
  </el-button>
</template>

<script>
  export default {
    data() {
      return {
        fullscreenLoading: false
      }
    },
    methods: {
      openFullScreen1() {
      // 当点击了指令方式时就会触发 loading加载效果  指令方式是使用v-loading方式指令这种形式
        this.fullscreenLoading = true;
        
        setTimeout(() => {
        // 2s之后关闭loading加载效果
          this.fullscreenLoading = false;
        }, 2000);
      },
      openFullScreen2() {
      // 当点击了 服务方式时  首先触发一个加载效果,loading中的参数对象就是配置项,让其显示何种样式的遮罩层
        const loading = this.$loading({
          lock: true,
          text: 'Loading',
          spinner: 'el-icon-loading',
          background: 'rgba(0, 0, 0, 0.7)'
        });
        setTimeout(() => {
        // 2s后关闭对应的遮罩层。
          loading.close();
        }, 2000);
      }
    }
  }
</script>

在这里插入图片描述
从逻辑上来说,我们前端每次在点击按钮之前,就设置上遮罩,当数据返还回来时就直接给这个遮罩层关了.

但是我们需要考虑的问题就是,如果我们这样去做,请注意,我们给每一个请求去添加loading效果,首先本身这就是一件非常费力的事情,当然如果产品有需求,要求严格指定什么需要添加loading效果的话,那么就必须去单独的去加了,不过最好还是封装一个全局的方法吗,然后去调用一下,这样肯定是比较好的,这个时候我们就可以在app.vue里使用provide、inject 这种方式来传递this调用这个父根方法,当然也可以main入口文件定义在prototype上,挂载在vue的原型对象上,到时候用的时候直接去调用即可.

3、配合axios,请求拦截器,相应拦截器使用loading效果。

在需求没有那么严格的情况下,首先我们肯定是有简单,高效的方法来解决多次点击按钮这个问题的,那么既然我们使用的是vue框架的话(当然其他框架像react也是同样一个道理,配置axios即可),我们就可以直接在axios的请求拦截器、响应拦截器中实现loading这个加载的效果。

首先我们来看axios的官网给出我们拦截器的api

在这里插入图片描述
拦截器
在请求或响应被 then 或 catch 处理前拦截它们。


// 添加请求拦截器
axios.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么
    return config;
  }, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
  });

// 添加响应拦截器
axios.interceptors.response.use(function (response) {
    // 对响应数据做点什么
    return response;
  }, function (error) {
    // 对响应错误做点什么
    return Promise.reject(error);
  });

我们就可以根据拦截器来做一系列的事件

直接上代码

import axios from 'axios'
import router from '@/router'
import qs from 'qs'
import { Loading } from 'element-ui'; // 记住按需导入
// 因为我在这边是使用的自定义的axios 性质是一样的,定义了一个全局变量,根据此全局变量来跟进
const service = axios.create({
  baseURL: '',
  timeout: 30000,
  withCredentials: true
})
// 请求拦截器
let loadingInstance = ''
service.interceptors.request.use(config => {
  // 增添token
  config.headers['Content-Type'] = 'application/x-www-form-urlencoded'
  loadingInstance = Loading.service({
    lock: true,
    text: 'Loading',
    spinner: 'el-icon-loading',
    background: 'rgba(0, 0, 0, 0.7)'
  });
  return config
}, err => {
  Promise.reject(err)
})
// 响应拦截器
service.interceptors.response.use(response => {
  // 以服务的方式调用的 Loading 需要异步关闭
  loadingInstance.close();

  // 如果正常直接返回对应data请求数据
  return response.data
}, err => {
  return Promise.reject(err)
})

此样即实现了全局效果,但是如果说真的就一点问题都没有了吗?
那肯定不是的,注意,一旦当我们返还了数据之后对应的loading加载效果就已经清空,但是如果一个页面加载的时候发送传递了多条请求呢?项目中一个页面是不可能只发送一个请求的。

我们上方,但凡只要有数据返还那么就会去除loading效果,那如果其他的数据没有返还回来呢?loading是不是还应该在一个加载的过程中?

4、改写、完善Loading加载效果

// 请求拦截器
let requestNum = 0
let loadingInstance = ''
service.interceptors.request.use(config => {
  // 每次请求时requestNum++
  requestNum++
  config.headers['Content-Type'] = 'application/x-www-form-urlencoded'
  loadingInstance = Loading.service({
    lock: true,
    text: 'Loading',
    spinner: 'el-icon-loading',
    background: 'rgba(0, 0, 0, 0.7)'
  });

  return config
}, err => {
  // 如果请求一旦出现问题 requestNum = 0 loadingInstance.close();
  requestNum = 0
  loadingInstance.close();
  Promise.reject(err)
})
// 响应拦截器
service.interceptors.response.use(response => {
  // 每次请求时-- 主要时用于判断当前共请求了多少次,如果返还的次数不等于请求的次数的话就不会进入这个条件
  // 只有当所有数据全返还时,才会关闭loading效果
  requestNum--
  if (requestNum <= 0) {
    loadingInstance.close();
    requestNum = 0
  }
  // 如果正常直接返回对应data请求数据
  return response.data
}, err => {
  // 如果请求一旦出现问题 requestNum = 0 loadingInstance.close();
  requestNum = 0
  loadingInstance.close();
  return Promise.reject(err)
})

这样当所有页面全部返还之后才会将loading加载效果关闭

幂等性解决方案 如订单业务中,存在状态「1-已下单,2-已支付,3-已完成,4-已取消」,按照业务流程,状态是依次流转的,所以在update操作时,我们就要根据本次的状态来更新下一次的状态。如果此时有多个相同的请求,可能会导致用户的金额变为负数。某些业务场景,是允许重复数据存在的,仅在流程的某个环节才不允许出现重复数据,这种情况直接在表中添加唯一索引是不合适的,所以就需要创建一张去重表。分布式锁的逻辑是,每次请求都通过业务唯一ID来尝试获取锁,如果获取成功,就进行后续业务逻辑操作,如果获取失败,就舍弃请求直接返回。 阅读详情

相关推荐

幂等性在前端开发中的最佳实践

使用 HTTP 方法的幂等性:HTTP 协议中的 GET 和 HEAD 方法是幂等的,而 POST 方法默认不是幂等的。使用 HTTP 方法的幂等性:HTTP 协议中的 GET 和 HEAD 方法是幂等的,而 POST 方法默认不是幂等的。在本文中,我们将介绍一些幂等性在前端开发中的最佳实践,并提供相应的源代码示例。使用请求头进行幂等性标记:可以在请求头中添加一个自定义的幂等性标记,用于标识请求的幂等性。使用请求头进行幂等性标记:可以在请求头中添加一个自定义的幂等性标记,用于标识请求的幂等性。

IOWEL的博客 278

Dsh016 爬虫基础--爬虫简介

1、通讯协议 1.1 端口 通常数据通讯可以分为几步: (1) 找到对方的IP(类似于打电话先查找联系人) (2) 数据要发送到对方指定的应用程序(比如微信、QQ、钉钉等)上。为了标识这些应用程序,给这些网络应用程序都用数字进行了标识,每一个应用的标识都是独立的,这些用于标识的数字称为端口。为了区别诸如网络接口等物理端口,一般称这些数字端口为‘逻辑端口’。 (3) 定义通讯规则。这个通讯规则一般称之为协议。 1.2 通讯协议 国际组织定义了通用的通信协议 TCP/IP协议,既可用于局域网,也可用于

weixin_44104354的博客 999

点击按钮触发Loading加载动画特效实现

2006年,John Resig 发布了 jQuery —— 当时没人想到这个小小的库会彻底改变前端开发的格局。它的口号很简单:“write less, do more”。那时候的前端世界是什么样?IE6 还在横行霸道,和各自为政,写得满屏都是,CSS 选择器只能靠自己手动遍历……开发体验堪比刀耕火种。jQuery 像一场及时雨,带来了三大革命性变化:统一的选择器引擎(Sizzle)跨浏览器的事件封装链式调用的 API 设计。

weixin_34581040的博客 601

使用CMD窗口模拟HTTP请求

使用CMD窗口模拟HTTP请求可以让初学者更直观的了解HTTP请求包的概念。

北冥同学的成长记录笔记 5015

PyTorch转ONNX遇到算子不支持?3种实战解决方案+TensorRT适配技巧

本文针对PyTorch模型导出ONNX时常见的算子不支持问题,提供了从诊断到解决的完整实战指南。首先讲解如何精准定位错误根源,随后详细介绍了三种核心解决方案:注册缺失的符号映射、实现自定义算子,以及为TensorRT开发插件的终极落地方案。文章还分享了构建稳健部署流水线的工程化实践,帮助开发者系统性地解决模型部署中的算子兼容性挑战。

fern8的博客 843

纯相位全息图优化算法综述

除此之外,还有许多用于减少斑点噪声的非迭代方法,例如:采用下采样掩膜的采样纯相位全息图(Sampled-Phase-only Hologram)方法、模式化相位掩膜(Patterned Phase-Only Hologram)方法、双相位方法(Double-Phase Method),以及使用非随机相位掩膜的方法(Random Phase-Free Method)等。迭代算法通常由一个对目标全息图的近似出发,经过一系列的重复操作不断优化这个近似全息图,直到该近似所得到的重建图像满足一定的误差要求;

ZhongKeWeiXing的博客 1428

Axios拦截器实战:如何通过全局Loading优化前端请求幂等性

本文深入探讨了如何利用Axios拦截器实现全局Loading,以优化前端请求的幂等性。文章从基础实现入手,逐步分析了并发请求导致Loading闪烁的问题,并提出了基于计数器的智能解决方案。进一步介绍了可配置化的进阶玩法,区分全局、局部和按钮Loading,以满足复杂场景需求,并提供了实战避坑指南。

b3n4m5q6w7的博客 262

InsightFace(RetinaFace + ArcFace)人脸识别实战:从模型部署到Web服务构建

本文详细介绍了如何利用InsightFace框架,结合其集成的RetinaFace人脸检测与ArcFace人脸识别预训练模型,从零开始构建一个高性能的Web人脸识别服务。内容涵盖环境搭建、模型部署、核心代码解析(包括五点仿射对齐关键步骤)、FAISS向量检索集成以及基于FastAPI的Web服务开发,并提供了实战优化与常见问题排查指南,帮助开发者快速实现工业级应用。

weixin_29054245的博客 227

element UI中loading加载框的花式用法

前端为了优化体验效果必不可少的就是加载框loading的使用。接口是异步的,获取数据是需要时间的,万一网络再卡顿下,总不能让用户干等着没数据的页面。那loading就必不可少了!

钱多多的博客 2万+

别再浪费HDRI了!D5渲染器环境光设置避坑指南(附天空球调试参数)

本文深入解析D5渲染器中HDRI环境光的高阶调试技巧,揭示90%渲染师常犯的错误认知。通过参数联动黄金法则、特殊材质应对方案及动态场景优化策略,帮助用户精准控制光子能量分布,实现建筑玻璃反射云层过渡等专业级效果。附赠天空球调试参数和商业项目验证案例,助您彻底释放HDRI潜力。

weixin_29216049的博客 495

ENVI5.6+SARscape实战:基于哨兵一号的PS与SBAS时序InSAR地表形变监测全流程解析

本文详细解析了使用ENVI5.6和SARscape软件基于哨兵一号数据进行PS与SBAS时序InSAR地表形变监测的全流程。从数据获取、预处理到PS-InSAR和SBAS-InSAR处理,提供了实用技巧和优化建议,帮助用户高效完成地表形变监测任务。

weixin_29245767的博客 1156

vue页面按钮呈现loading加载状态,与avue-form中loading使用问题

按钮点击时呈现加载状态,防止其他误操作。 1.效果图 2.代码实现 (1)按钮添加::loading="loading.listLoading" <el-button type="primary" style="margin-top: 12px;" :loading="loading.listloading" @click="expScorePacks()">导出 (2)定义 loading.listLoading(true:为开启加载状态,false:关闭加载状态) .

httpmc2018的博客 9793

在鸿蒙中使用AVPlayer完成视频的播放【坚果派】

播放的全流程包含:创建AVPlayer,设置播放资源和窗口,设置播放参数(音量/倍速/缩放模式),播放控制(播放/暂停/跳转/停止),重置,销毁资源。5.准备播放:调用prepare(),AVPlayer进入prepared状态,此时可以获取duration,设置缩放模式、音量等。8.退出播放:调用release()销毁实例,AVPlayer进入released状态,退出播放。6.视频播控:播放play(),暂停pause(),跳转seek(),停止stop() 等操作。今天我们来看一下视频如何正常播放。

坚果的博客 4057

layui loading动画_loading加载和layer.js

layer.js中的loading加载l本篇主要介绍layerjs中的loading加载在实际项目中的应用1、使用的技术前端:HTML5+CSS3+JS+layer.js后端:.net2、遇到的问题在使用layer.js插件中提供的loading时,需要在layer.js中的layer.css找到对应的gif格式动态图,此gif图需要和插件中的loading加载gif图大小尺寸相同3、layer....

weixin_39916479的博客 3936

如何在 SAP BTP 上使用 Integration Suite 消费 S/4HANA Cloud API

SAP Integration Suite是一个集成平台即服务(iPaaS),允许开发人员顺利地将内部部署和基于云的应用程序和流程与SAP管理的工具和预构建内容进行集成。登录 SAP Business Technology Platform Cockpit,进入 integration suite:再点击 API management 进入 API Portal:或者直接从收藏夹里打开链接:https://304a49cetrial.integrationsuitetrial-apiportal.cfapp

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1699

pi-coding-agent 完整详解

pi-coding-agent是一个由Mario Zechner开发的专业AI编程助手,基于Node.js和TypeScript构建。核心功能包括:1)多级思考模式(ThinkingLevel),从none到ultra控制推理深度;2)对话压缩(compaction)管理长对话记忆;3)WebSocket实时通信支持流式交互。该智能体支持代码生成、调试、重构等专业编程任务,采用AI Agent架构,具备工具调用和多轮记忆能力。项目结构通常包含server、agent、config等模块,可通过二次开发扩展功

大坡3D软件开发 2425

Vuesax Loading 组件完全指南:$vs.loading 全局加载函数的用法与源码原理剖析

本文以 Vuesax(Vue.js 2 组件框架)官方文档 [docs/components/loading.md](https://link.gitcode.com/i/b65f038142359040d13e8a34c12c56ec) 为核心骨架,系统讲解全局加载函数 `$vs.loading()` 的完整 API、7 种动画类型、颜色与背景配置、局部容器加载方式,以及 `text`、`tex

gitblog_00578的博客 990

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

vue 给el-button添加加载效果

需求:给子组件对话框“确定”按钮添加加载效果: (1)给按钮绑定: :loading="ConfirmLoading" (2)在data中初始化 ConfirmLoading: data() { return { ConfirmLoading: false } } (3)提交表单时设置: this.ConfirmLoading = true (4)对话框绑定closed事件,关闭对话框,关闭加载效果: <el-dialog class="u

有问题可关注公众号:前端研究院 后台输入问题回复 2332

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Vue 中使用 Element Plus 实现全局 Loading 效果并封装为高阶函数

本文展示了如何使用 Element Plus 的ElLoading组件实现全局加载动画,并通过高阶函数封装,让我们可以在不同的异步操作中方便地使用这个功能。这样的封装使得代码更加简洁和易维护,同时提升了用户体验。完整代码可以在你的项目中复用,且可以通过自定义参数适应不同的场景需求。希望这篇文章对你有所帮助!

眉开带眼笑的博客 4017

vue+element ui实现全局loading

应用场景 场景:前端在发送Ajax请求,请求后台数据时,不允许用户点击当前页面的其他按钮。 引入loading import { Loading } from 'element-ui'

Duke10的博客 1812

Vue项目实战:用Axios拦截器优雅解决重复提交问题(附完整代码)

本文详细介绍了在Vue项目中使用Axios拦截器优雅解决表单重复提交问题的实战方案。通过请求拦截器和响应拦截器的结合使用,实现全局防重复提交控制,并整合Loading效果提升用户体验。文章提供了完整的代码实现,包括请求标识生成、请求队列管理和错误处理等关键功能,帮助开发者构建更健壮的前端应用。

egg99的博客 946

loading加载和layer.js

layer.js中的loading加载l本篇主要介绍layerjs中的loading加载在实际项目中的应用1、使用的技术前端:HTML5+CSS3+JS+layer.js 后端:.net2、遇到的问题在使用layer.js插件中提供的loading时,需要在layer.js中的layer.css找到对应的gif格式动态图,此gif图需要和插件中的loading加载gif图大小尺寸相同 3、lay

weixin_37839390的博客 9602

layui正在加载遮罩层

1.场景 项目开发过程中,可能会遇到,后台响应很慢的情况,这是,前端就需要给出友好的提示,以便让用户有更好的体验。 拿我个人项目中的一个事例说一下,删除站点的时候,需要删除站点的数据明细,数据明细有100w左右,删除100w数据,响应的时长肯定很长,不可能让用户,傻傻的一直等把,以我的经验来说,我发现点击提交后,很久没有响应,我就觉得网站有问题,就会按F5刷新。 2.代码 //加...

程序猿学社的博客 2万+

【小程序-慕尚花坊04】网络请求并发与loading

深入理解网络请求并发与loading

m0_59269218的博客 1588

layui 增加loading图标防止用户重复点击保存或修改按钮影响后台执行

在对应submit按钮开始时 var index = layer.load(1, { shade: [0.5,'#000'] //0.1透明度的背景 }); 在响应成功时或失败时,对应关闭 layer.close(index); 如:

Wuhaotian1996的博客 8154

自定义Loading 加载,适用于 所有的按钮事件

页面加载时需要加载,请求接口也需要loading。在前端loading的需求无处不在,就是为了让用户体验更好。 效果图如下

m0_57071129的博客 800
上一篇: vue-Cli3,Vue-Cli4打包后如何配置静态资源路径?(自定义浏览器icon图标,title文本)
下一篇: 前端如何封装一个组件?怎么造轮子?手写js封装一个dialog弹窗组件。
归来巨星
归来巨星 新星创作者: 前端开发技术领域 新星创作者: 前端开发技术领域
博客等级 码龄7年 5391粉丝 95原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

归来巨星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值