如何全局防止ajax重复提交

在开发中一定有这种情况:

一个简易的需求,点一个按钮,则向服务器请求资源,不作处理时,多次点击后会有很多个请求在等待。

最粗暴的解决方式是点一次就将按钮disable掉,比如

$("input[type=submit]").attr('disabled',false)

但这种形式缺点也很多,还有稍微优雅一点的方式完全由JS来控制,就是使用一个变量来保存状态:

var post_flag = false; 
function post(){
    //如果正在提交则直接返回,停止执行
    if(post_flag) return; 
    //标记当前状态为正在提交状态
    post_flag = true;
    $.ajax({//进入AJAX提交过程
        url:'/post.php',
        data:{a:1,b,1}
    })
    .done(function () {
        // something
    })
    .always(function () {
        post_flag = false;
    })
}

但无论如何每个请求都需要写这样一段重复性的代码,又臭又长,还和业务逻辑混在一起,也不是最佳的解决方案。

那怎么才能把这个近似的业务逻辑封装起来呢?这里就用到了jquery ajax的预处理功能(一般其他的ajax工具也都有预处理函数)

这里只针对jquery:

!function () {
	/*设置ajax全局默认值*/
	$.ajaxSetup({
		async: true,
		cache: false,
		dataType: 'json'
	});
        /*ajax预处理缓存*/
	var ajaxRequestList = {};
	/*
	 	判断唯一标识,同一个ajax只能同时存在一次
	 	single(string): 唯一标识 
	 	mine(boolean): 如果ajax标识重复则用自身(true)还是原来的
	 	once(boolean): 是否唯一,唯一(true)则只会请求成功一次
	 */
	$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
		if (typeof originalOptions.single === 'string') {
			if (!ajaxRequestList[originalOptions.single]) {
				ajaxRequestList[originalOptions.single] = jqXHR;
				if (originalOptions.once === true) {
					jqXHR.fail(function() {
						delete ajaxRequestList[originalOptions.single];
					});
				} else {
					jqXHR.always(function() {
						delete ajaxRequestList[originalOptions.single];
					});
				}
			} else {
				if (originalOptions.mine === true) {
					ajaxRequestList[originalOptions.single].abort();
				} else {
					jqXHR.abort();
				}
			}
		}
	});
}();

基本思路就是利用预处理器ajaxPrefilter将请求信息储存在一个对象中,可以通过传入的额外标志来控制重复提交

$.ajax({
	url: 'post.php',
	type: 'POST',
	data: {id: 0},
	single: 'post_1' // 唯一标识 当有这个标识存在,预处理器会拦截本次请求
})
.done(function (data) {
	// something
});
$.ajax({
	url: 'post.php',
	type: 'POST',
	data: {id: 0},
	single: 'post_2',
        mine: true // 当single重复时用自身并放弃之前的ajax请求
})
.done(function (data) {
	// something
});
$.ajax({
	url: 'post.php',
	type: 'POST',
	data: {id: 0},
	single: 'post_3',
        once: true // 只允许请求成功一次,一旦成功,这个single永远不会在发起请求
})
.done(function (data) {
	// something
});
通过预拦截器和这三个标识,可以很方便的应对基本所有情况,在项目中也没用发现任何问题




阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页