-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[js] Ajax请求防抖实现 #2
Comments
var flag = 0;
$.smartAjax = function (args) {
var fn = arguments.callee;
$.ajax({
url: args.url,
data: { },
type: args.type,
dataType: "text",
beforeSend: function () {
flag += 1;
// 已请求过
if (flag > 1) {
if (args.smartType == 0) {
flag = 0;
//setTimeout(alert("aaa"), 10000); 这里的setTimeout无论这只多长时间都是立即执行。不知为什么。
(function () {
var i = 0;
var interval = setInterval(function () {
console.log(i);
i++;
if (i == 5) { clearInterval(interval); fn(args); };
}, 100);
})();
return false;
} else if (args.smartType == 1) {
alert("不能发请求。");
return false;
}
}
},
success: function (result) {
args.success(result);
flag = 0;
},
error: function () {
flag = 0;
}
});
}; 只能算是最基本的实现,还有无限优化的空间。 |
为扩充提供无限可能,两个方案,两种实现方式。大家有优化点可以给出建议~!! /**
* Created by 二狗 on 2015/12/10.
*/
var protectiveStrategy = {
timer : function() {
var url = [].pop.call(arguments),
ms = +([].pop.call(arguments)),
self = arguments.callee,
now = new Date().getTime();
ms = (typeof ms === 'number' && ms <= 2000) ? ms : 500;
if(!self.preTime || (now-self.preTime >= ms)) {
self.preTime = now;
$.ajax({
url : url,
//...
success : function() {
}
});
}
},
responsed : (function () {
var canSend = true,
url = [].pop.call(arguments);
return function() {
if(canSend) {
canSend = false;
$.ajax({
url : url,
//...
success : function() {
canSend = true;
}
});
}
}
}())
};
/**
*
* @param {String} plan 计划用何种方式代理,可选择的值为策略对象的key
* @param {String} url 请求的URL
*/
var ajaxProxy = function(plan ,url) {
var ary = plan.split(':'),
strategy = ary.shift();
ary.push(url);
protectiveStrategy[strategy].apply(null ,ary);
};
$.smartAjax = ajaxProxy;
function onClick() {
$.smartAjax('timer:1000' ,'localhost:8080');
//$.smartAjax('responsed' ,'localhost:8080');
} |
不要有全局变量污染,尽量都写在 |
//还差一步,就是$.smartAjax得到的方法不能在方法体内保存,要先用变量保存起来,智商不够
$.smartAjax = function(opts) {
var that = this,
proxyFn = function(type,options,context) {
var resFn;
if(type===0) {
resFn = (function(){
var _first = true,
startTime = +new Date();
return function(){
if(_first) {
_first = false;
$.ajax(options);
return;
}
var now = +new Date();
if(now - startTime < 500 ){
return;
}
startTime = now;
$.ajax(options);
}
})()
}else {
resFn = (function(){
var _completed = true,
completeFn = options.complete;
options.complete = function(){
completeFn&&completeFn();
console.log('完成');
_completed = true;
}
return function(){
if(_completed) {
_completed = false;
$.ajax(options);
}
}
})()
}
return resFn;
},
smartType = opts.smartType||0;
delete opts.smartType;
var resFn = proxyFn(smartType,opts);
return resFn;
}
//测试代码
//要先用after500保存下
var after500 = $.smartAjax({
smartType:0,
url:'http://localhost/test.php',
success:function(response){console.log(response)}
});
/*var complete = $.smartAjax({
smartType:1,
url:'http://localhost/test.php',
success:function(response){console.log(response)}
});*/
var a = 1;
var timer = setInterval(function(){
if(a==20) {
clearInterval(timer);
}
a++;
after500()
//complete();
},200) |
@VaJoy 还差个return $.ajax(options); ;(function() {
var limitPendingRequests = {};
$.ajaxSetup({
// 不缓存get
cache: false,
beforeSend: function(xhr, settings) {
// ajax 请求限制
var self = this;
var port = (function() {
var url = self.url;
var index = url.indexOf('_');
return index < 0 ? url : url.substring(0, index - 1)
}());
if (typeof settings.smartType === 'undefined') {
return true;
}
//500 毫秒下一次
if (settings.smartType === 0) {
if (limitPendingRequests[port]) {
return false;
}
limitPendingRequests[port] = true;
setTimeout(function() {
delete limitPendingRequests[port];
}, 500);
return true;
}
//请求完成进行下一次
if (settings.smartType === 1) {
if (limitPendingRequests[port]) {
return false;
}
limitPendingRequests[port] = true;
xhr.complete(function() {
delete limitPendingRequests[port];
});
return true;
}
return true;
}
});
})();
/*//
$.ajax({
smartType:0// 1,
xxxx
})*/
//这样做会触发ajaxError 事件,不过可以根据事件参数来判断是不是主动给取消了,参数有个值是canceled |
@LittleBearBond 你貌似艾特错人了吧?我没提交过代码,如果要我写我会这么写: $.smartAjax = (function () {
var _time_start = 0,
_flag = 1; //用于判断是否可以发送请求
return function (opt) {
var noop = function () {},
validFun = function (f) {
return typeof f === 'function' ? f : null
},
smartType = opt && opt.smartType,
processResponse = function (callback) {
['success', 'error'].forEach(function (resFunName) {
var resFun = validFun(opt[resFunName]) || noop;
opt[resFunName] = function () {
callback();
resFun.call(this, arguments)
}
});
},
typeCallback = {
0: function () {
_flag && (_time_start = Date.now());
if(_flag==0 && Date.now() - _time_start > 300) {
_flag = 1;
_time_start = Date.now()
}
},
1: function () {
if(_time_start) { //防止先调用smartType=0再调用smartType=1会失效
_flag = 1;
_time_start = 0
}
processResponse(function(){
_flag = 1;
})
}
};
var hasSmartType = typeCallback[smartType];
hasSmartType && typeCallback[smartType]();
if(_flag) {
hasSmartType && (_flag = 0);
return $.ajax(opt);
} else {
return $.Deferred()
}
}
})(); 不存在外部变量,也不用占用什么beforeSend,也可以正常使用 |
<button id="req1">
请求 smartType:1
</button>
<button id="req2">
请求 smartType:2
</button> /*
smartType:1 => 500ms 只能发送一次
smartType:2 => 等待请求返回后才能再次发起
*/
$.smartAjax = function(args) {
var send = function(opts) {
$.ajax(opts);
};
var afterSuccess = args.success;
var afterError = args.error;
return function() {
var exec = [
function() {
if (!send) return;
var oldSend = send;
send(args);
send = null;
setTimeout(function() {
send = oldSend;
}, 500);
},
function() {
if (!send) return;
var oldSend = send;
args.success = function(result) {
send = oldSend;
afterSuccess(result);
};
args.error = function(result) {
send = oldSend;
afterError(result);
};
send(args);
send = null;
}
];
exec[args.smartType - 1]();
};
};
var send1 = $.smartAjax({
smartType: 1,
url: 'http://sandbox.runjs.cn/show/teu1xt1n'
})
var send2 = $.smartAjax({
smartType: 2,
url: 'http://www.google.com',
success: function(data) {
//console.log(data);
console.log('data')
}
})
$('#req1').click(function() {
send1();
});
$('#req2').click(function() {
send2();
}); |
想破头了,依然没什么头绪。坐等最佳实践。 var queue = { //创建队列,点击按钮将请求添加到队列,然后按照固定时间释放
queStore : [],
length : 0,
timeout : 2000,
timer : null,
add : function(arg){
this.queStore.push(arg);
this.length++;
return this;
},
remove : function(i){
this.queStore.splice(i,1);
this.length--;
return this;
},
dequeue : function(){
if(queue.length>0){
var a = queue.queStore.shift();
queue.length--;
a();
}else{
clearInterval(this.timer);
}
},
fire : function(){
clearInterval(this.timer);
this.timer = window.setInterval(function(){queue.dequeue.call(queue);},this.timeout);
}
};
var flag = true;
$.smartAjax = function(arg){
var def = {
smartType:0,
url:"",
type:"POST",
success:null
};
var ajaxFun = function(){
$.ajax({
url:opation.url,
type:opation.type,
success:opation.success
});
};
var opation = $.extend(def,arg);
queue.add(ajaxFun);
switch(opation.smartType){
case 0 :
queue.fire();
break;
case 1 :
//另外一套逻辑。
break;
default:
throw new Error("参数类型错误!");
}
} |
@qianduanMortal 其实不用搞队列,防抖的初衷本来就是忽略冗余的请求 |
Open
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
现在有一个按钮 $btn,我们给它绑定了点击事件,让它点一次就发一次POST请求去后端提交统计数据:
但是如果用户在很短的时间内点了好几下按钮(比如在1s里快速地点了5下),会向服务器发送很多条数据,这样并发量大的情况下服务器可能吃不消。
而且有时候我们也希望当前一条请求结束了(服务器返回数据了)之后才可以发起第二条请求。
所以请你封装一个叫
$.smartAjax
方法来做防抖处理,它可以有一个参数smartType
用于确定防抖方式——如果其值为 0 则要求在 500ms 内只允许发出一条请求;如果参数
smarType
值为 1 则表示只允许在前一条收到服务器响应(包括失败的响应)后才可以继续发送新请求。示例:
The text was updated successfully, but these errors were encountered: