ajax请求,是局部刷新,页面不一定会跳转。这就面临着一个问题,如果用户的网络出现波动或是网络慢,就可能会出现用户多次点击,造成重复请求的问题。解决方法,可以在用户点击了按钮之后,先禁用按钮,等ajax请求响应了之后,再让按钮恢复可用状态。但是如果网站里ajax请求很多的话,这样做,就有点不合适了。
一开始,我的想法是,能不能封装一个函数,所有的ajax请求都由这一个函数来发送,然后在这个ajax请求里面做一些处理,这样就可以解决重复请求的问题。于是就有了下面的函数
function sendAjax(ajaxContent){
$(\'#king_mask\').show;
var success = ajaxContent.success;
ajaxContent.success = function(data){
$(\'#king_mask\').hide();
success(data);
};
$.ajax(ajaxContent);
}
然后,页面所有的ajax请求,都不再使用$.ajax函数来发送,改用sendAjax函数来发送,参数和$.ajax函数一样,接收一个json对象。#king_mask,就是一个div,一个盖住了整个页面的遮罩层。这个方法就比较简单了,是最原始的封装。使用这个方法,需要别人在自己的页面创建一个#king_mask的div,使用起来不方便。而且如果别人所有的页面都已经写好了,后面再使用这个方法,意味着要把代码里所有的$.ajax改成sendAjax,工作量可能就比较大,而且,通常程序员都不愿意干这一类事情。
我们在设计方法的时候,都要尽量地做到非侵入。所谓的非侵入,就是别人使用你写好的方法,原先的代码,不用动,如果哪一天,不想用你写的方法了,只要把你的方法删除,代码也不用动,功能还能正常运行。基于这样的思想,再改写这个函数,把#king_mask放到js中来维护。同时,在上面的函数内,通过改写ajaxContent的success,可以让ajax请求响应成功后,隐藏遮罩层,那在外层,为什么不可以改写$.ajax函数呢?基于这样的想法,代码更改如下
(function(){
//页面加载完成后,把遮罩层添加进页面
$(function(){
$(\'<div id=\"king_mask\"></div>\')
.css({\'background-color\':\'black\',\'position\':\'absolute\',\'left\':\'0\',\'top\':\'0\',\'opacity\':\'0.2\',\'z-index\':\'99999\'})
.appendTo($(\'body\'));
});
//改写$.ajax函数
var fun = $.ajax;
$.ajax = function(ajaxContent){
//让遮罩层的宽高等于文档的宽高,因为文档的宽高,随时可能会变,所以每次就重新赋值,并显示出来
$(\'#king_mask\').width($(document).width()).height($(document).height()).show();
var success = ajaxContent.success;
var error = ajaxContent.error;
ajaxContent.success = function(data){
$(\'#king_mask\').hide();
success(data);
}
ajaxContent.error = function(data){
$(\'#king_mask\').hide();
error(data);
}
fun(ajaxContent);
}
})()
这样一来,别人使用这个方法,就不用关心遮罩层的创建了,也不用改写方法,直接像以前一样,使用$.ajax函数发送ajax请求,就可以了。现在新的问题是,如果用户的网络很慢,甚至后面直接断掉了网,这个时候,ajax请求就不会有响应了,也就意味着遮罩层会一直盖在页面上,这样就不好了。简单点做,可以给ajax请求设置一个超时时间,超过这个时间没有响应就会走error函数。简单的方法,我肯定不会用的。。。
我的做法是,设置一个超时时间,如果用户在超时时间之前,点击遮罩层,是没有反应的,在超时时间之后,用户点击遮罩层,会取消ajax请求,并同时给出一个提示语“请求数据失败,请重试!”,这样一来,可以把超时时间设置的比较小,然后依据用户的忍耐度不同,在超时时间过后,随时可以点击遮罩层,取消ajax请求的发送。最终的代码
(function(){
//声明一个全局的变量,用来存放一些配置参数
window.domain = {};
//ajax请求的超时时间,发送ajax请求,在这个时间之后,没有响应,用户点击遮罩层,会取消ajax请求,单位:毫秒
domain.ajaxTimeout = 2000;
//页面加载完成后,把遮罩层添加进页面
$(function(){
$(\'<div id=\"king_mask\"></div>\')
.css({\'background-color\':\'black\',\'position\':\'absolute\',\'left\':\'0\',\'top\':\'0\',\'opacity\':\'0.2\',\'z-index\':\'99999\'})
.appendTo($(\'body\'))
.click(function(){
//遮罩层的点击事件,当domain.flag为真,并且domain.xhr(ajax请求对象)有值,才会关闭domain.xhr
if(domain.flag && domain.xhr){
domain.xhr.abort();
domain.xhr = null;
$(\'#king_mask\').hide();
alert(\"请求数据失败,请重试!\");
}
});
});
//改写$.ajax函数
var fun = $.ajax;
$.ajax = function(ajaxContent){
//让遮罩层的宽高等于文档的宽高,因为文档的宽高,随时可能会变,所以每次就重新赋值,并显示出来
$(\'#king_mask\').width($(document).width()).height($(document).height()).show();
//开启一个一次性的定时器,超时时间过后,domain.flag设置为true,这个时候遮罩层的点击事件就满足一个条件了
domain.timer = setTimeout(function(){domain.flag = true;}, domain.ajaxTimeout);
var success = ajaxContent.success;
var error = ajaxContent.error;
ajaxContent.success = function(data){
clearTimeout(domain.timer);
domain.flag = false;
domain.xhr = null;
$(\'#king_mask\').hide();
success(data);
}
ajaxContent.error = function(data){
clearTimeout(domain.timer);
domain.flag = false;
domain.xhr = null;
$(\'#king_mask\').hide();
error(data);
}
domain.xhr = fun(ajaxContent);
}
})()
代码并不多,逻辑应该也不算复杂吧。这里使用了一个全局的变量——domain,在后面的页面中,还有很多地方,会使用到这个变量。
在编码的过程中,我的思想一直是:功能的实现,并不是编码的结束,而是编码的开始。所以我经常是,写了几十行代码,实现了一个功能,然后,我可以对这几十行代码,一遍又一遍的修改,让所写的代码,更通用,更易用,更高效。写一万行普通的代码,不如写一百行精炼的代码。
继续阅读与本文标签相同的文章
云场景实践研究第60期:信号旗智能科技
-
浏览器事件机制中 事件触发的三个阶段
2026-05-19栏目: 教程
-
德媒:德国5G安全标准“一视同仁”,5G建设不排除华为
2026-05-19栏目: 教程
-
简单了解 JavaScript的组成
2026-05-19栏目: 教程
-
阿里云如何备份虚拟机?
2026-05-19栏目: 教程
-
elasticsearc使用指南之ES管道聚合(Pipeline Aggregation)
2026-05-19栏目: 教程
