JS前端无侵入实现防止重复提交请求技术
JS前端无侵入实现防止重复提交请求技术
最近在代码发布测试的过程中,我发现有些请求非常的消耗服务器资源,而系统测试人员因为响应太慢而不停的点击请求。我是很看不惯系统存在不顺眼的问题,做事喜欢精益求精,也很喜欢和别人争论技术,有时候硬要争得你死我活。
实在看不下去系统存在这个问题,下定决心好好整改一波,我们系统几乎都是使用Ajax技术发请求,使用的是针对我们系统特点对jQuery的post方法进行了封装的newpost方法,这个方法扩展了异常响应,登陆超时,token验证,加载时渲染等自动完成功能,参数不变,也是我写的。由于系统模块很多,功能很强大,代码也很多,为了统一使用此方法,花了不少时间将post修改成newpost。这次为了限制请求次数这个小功能,我请示了领导并把初步的方案说与他听,他同意了我做此次修改。
我调查了几个有防止请求重发控制的页面,几乎都是发起请求后到响应这段时间对按钮置灰警用处理,这种方案有很多的缺点,如:
1. 长时间未响应的请求给人不友好的体验
2. 需要针对每个按钮做请求前后的控制,会因为处理各种小问题而变得难以维护
3. 业务与控制逻辑混合在一起使得函数功能不单一
我最初的想法就是想找到一种类似于面向切面的无侵入页面的方式实现请求限制,因此想到了如下方案:
1. 只控制用户最后一次的请求
2. 第一次请求未响应之前一分钟之内不发相同的请求
3. 如果前一次请求得到了响应,那么第二次相同的请求也不做限制
后来发现这种方案行不通,主要有以下几个方面的原因:
1. 大多数页面每交互一次都会发起多个不同的请求。
2. 没个请求响应的时间也不一样,可能后发的请求先响应
我把这种想法告诉了导师,经过一番争论后认为我无法通过不侵入的方式实现这样的功能,按照他的想法,我得修改整个项目有请求的代码,完全低估了我对JS的了解,后来我独自优化了方案,不在只控制最后一个请求,代码实现的大纲如下:
发起POST请求前处理逻辑
1. 获取全局上下文中的存储请求信息的数组变量
2. 遍历请求响应数组
3. 清理大于两分钟未响应的请求,防止页面长时间不响应
4. 找到了与本次相同的请求
a) 如果请求小于200ms,则判断为系统行为,直接将环境和回调函数压入已有请求的调用栈,否则替换之前的请求的调用栈
b) 不发请求
5. 没有找到与本次相同的请求
a) 将请求信息、时间、调用环境和回调函数压进请求响应数组,请求URL和条件con作为唯一标识,调用栈也是一个由当前环境和回调函数组成的数组,使用数组解决相同的请求(url和con都一样)
b) 发起请求
请求响应后处理逻辑
1. 获取全局上下文中的存储请求信息的数组变量
2. 遍历请求响应数组
3. 找到了与此响应相同的请求
a) 遍历此请求的调用栈并依次调用回调函数
b) 删除已经处理的请求
4. 没有找到与此响应相同的请求则什么都不做
具体实现:
/*@description 自定义事件
*@method_costomEvent
*@formuphy
*/
muphypost: function (url, condition, callback, type, option) {
if (typeof condition === 'function') {
option = type;
type = callback;
callback = condition;
condition = {};//jQuery:condition = undefine;
}
let that = this, reqUrl = (url + JSON.stringify(condition)).substr(0, 1000);
//判断是否需要发起请求
let hasReq = beforePost();
if (hasReq === true) {
return that;
}
//新增请求Token
muphy.addToken(condition);
//借助jQuery发请求
$.post(url, condition, function (data, status){
afterPost(data, status);
}, type);
return that;
//请求前处理函数
function beforePost() {
//获取历史请求
let postHistory = muphy.postHistory, now = new Date();
//遍历请求响应数组,找到与此请求相同的请求
for (let i = 0; i < postHistory.length;i++) {
if (now - postHistory[i]._startTime > 120000) {
//清理大于两分钟未响应的请求
postHistory.splice(i, 1);
} elseif (postHistory[i]._reqUrl === reqUrl){
//找到了就更新请求时间,并将执行环境和回调函数放入请求响应数组的调用栈;
//小于200ms判定为系统行为直接将环境和回调函数压入已有请求的调用栈,
//否则替换之前的请求
if (now - postHistory[i]._startTime < 200) {
postHistory[i]._startTime =now;
postHistory[i]._handles.push({ _callback: callback, _this: that });
} else {
postHistory[i]._handles =[{ _callback: callback, _this: that }];
}
//返回true 表示本次不发请求
return true;
}
};
//没找到与此相同的请求时将请求信息、时间、调用环境和回调函数压进请求响应数组
postHistory.push({ _reqUrl: reqUrl,_startTime: new Date(), _handles: [{ _callback:callback, _this: that }] });
//返回false 表示本次需要发请求
return false;
}
//请求后处理函数
function afterPost(data, status) {
//获取请求响应数组
let postHistory = muphy.postHistory;
//遍历请求响应数组,找到与此请求相同的请求
for (let i = 0; i < postHistory.length;i++) {
if (postHistory[i]._reqUrl === reqUrl) {
//找到相同的请求,遍历此请求的调用栈并调用
muphy.each(postHistory[i]._handles, function () {
this._callback.call(this._this, data, status);
});
//调用完成删除已经处理的请求
postHistory.splice(i, 1);
break;
}
}
}
}
JS前端无侵入实现防止重复提交请求技术的更多相关文章
- ajax防止重复提交请求1
ajax防止重复提交请求 A. 独占型提交 只允许同时存在一次提交操作,并且直到本次提交完成才能进行下一次提交. module.submit = function() { if (this.pro ...
- JS中如何防止表单重复提交问题
在登录页面html中写如下代码 <script type="text/javascript"> var issubmit=false; function dosubmi ...
- 使用js是想防止表单重复提交的效果
直接上代码: <html> <head> <title>Form表单</title> <script type="text/javasc ...
- js 前端向服务器端传送文件的常用请求方式
在做项目的过程当中写到文件上传的功能,想着之前也是踩坑过来的,就在这里总结下自己常用的方法吧.我们现在一般都是通过ajax来搭起前后端数据交互的桥梁,但是大家在做到有文件需要上传的时候就会发现我们用a ...
- java web解决表单重复提交问题
我们大家再进行web开发的时候,必不可少会遇见表单重复提交问题.今天就来给总结如何解决表单提交问题,欢迎大家交流指正. 首先我们在讨论如何解决表单重复提交问题之前先来解决三个问题:1.什么叫表单重复提 ...
- java web解决表单重复提交
首先我们在讨论如何解决表单重复提交问题之前先来解决三个问题:1.什么叫表单重复提交?2.什么情况下会出现表单重复提交?3.什么情况需要避免表单重复提交? 什么叫表单提交问题,说白了,就是同一份信息,重 ...
- php解决表单重复提交
php解决表单重复提交时间:2015-2-28 | 评论:1条评论 | 被查看了 189 次 | 标签:php, W3cui重复提交是我们开发中会常碰到的一个问题,除了我们使用js来防止表单的重复提交 ...
- PHP防止表单重复提交的解决方法
PHP+SESSION防止表单重复提交 index.php 当前表单页面is_submit设为0 SESSION_START(); $_SESSION['is_submit'] = 0; <fo ...
- php 解决表单重复提交实现方法介绍
重复提交是我们开发中会常碰到的一个问题,除了我们使用js来防止表单的重复提交,同时还可以使用php来防止重复提交哦. 例1 代码如下 复制代码 <?php/* * php中如何防止表单的重复提 ...
随机推荐
- 【大数据安全】CDH集群禁用Kerberos
在调试Kerberos的时候可能会有需要禁用的场景.以下是各组件禁用Kerberos的相关配置. 环境 CDH版本:5.11.2 Linux版本:7.4.1708 Docker版本:Docker ve ...
- DSAPI 短域名服务
有时,需要将长域名转换为短域名,或是为了减少字符量,或是为了隐藏真实网址.在DSAPI中,集成了EPS-GS的短域名接口.该功能需要联接互联网,从EPS服务器获取. 代码 DSAPI.网络.短域名服务 ...
- 【转载】 Sqlserver中通过Select Into语句快速单表备份
在Sqlserver数据库中,备份数据的方式有很多种,可以使用整个数据库备份,也可使用导出包含数据和架构的脚本文件的方式来进行单表或多表数据的备份,其实还有一种Select Into的方式可以快速备份 ...
- MySQL 笔记整理(13) --为什么数据表删掉一半,表文件大小不变?
笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 13) --为什么数据表删掉一半,表文件大小不变? 我们还是以MySQL ...
- 了解spring
一.spring简介 Spring是一个JavaEE轻量级的一站式的开发框架(spring的可插拔特性,企业用于整合其他框架)轻量级:使用最少的代码启动程序,根据所需选择功能选择模块使用一站式:提供了 ...
- 在react中实现打印功能
最近项目中,前端采用react+antd+dva的组合,已经完成了后头管理类系统产品的更新迭代工作. 今天有一个新需求,需要在后台管理系统中实现点击打印完成指定页面的打印功能. 之前也没接触过,只知道 ...
- Visual Studio插件开发基础
Visual Studio插件主要有两种:Add-in 和 VSX(Visual Studio eXtensibility) 两者区别可参考这篇文章:Visual Studio Extensions ...
- Git 安装 on centos7
本文演示如何在CentOS7上安装和使用git. 1 准备工作 1.1 浏览器访问安装包下载地址: https://www.kernel.org/pub/software/scm/git/ 找到下载列 ...
- 把ESXi中的虚拟机通过OVA/OVF导出的方式迁移到Proxmox 5
引用地址:https://blog.csdn.net/zebra2011/article/details/83046841 一.前言 之前发现ESXi是免费的时候,非常兴奋地把几台服务器都装上了 ...
- composer在update时提示file could not be downloaded: SSL operation failed with code 1. OpenSSL Error messages: error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO
在开发的时候,需要把依赖的服务更新到最新,然后 手动composer update一下,提示如下: failed) Update failed (The "e "https://a ...