我有一个搜索输入,它会监听keyup
和change
以通过Ajax触发listview的更新。
看起来像这样:
input.on('keyup change', function(e) {
if (timer) {
window.clearTimeout(timer);
}
timer = window.setTimeout( function() {
timer = null;
val = input.val();
el = input.closest('ul');
// run a function - triggers Ajax
widget[func](dyn, el, lib_template, locale, val, "update");
}, interval );
});
所有工作都很好,除了超时和绑定的处理,这导致双Ajax请求被放置而不是单个(当keyup
通过时,change
事件触发相同的Ajax再次请求)。
我可以通过添加另一个超时来“修复”这个:
var runner = false;
input.on('keyup change', function(e) {
if ( runner === false ){
runner = true;
if (timer) {
window.clearTimeout(timer);
}
timer = window.setTimeout( function() {
timer = null;
val = input.val();
el = input.closest('ul');
widget[func](dyn, el, lib_template, locale, val, "update");
// ssh....
window.setTimeout( function(){ runner = false; },2500);
}, interval );
}
});
但这根本不好......
问题:
我如何确保两个绑定同时触发,我需要的功能只运行一次?
谢谢!
修改:
这里触发了Ajax调用:
widget[func](dyn, el, lib_template, locale, val, "update");
调用此函数来构建动态列表视图
buildListView : function( dyn,el,lib_template,locale,val,what ){
...
// this calls my AJax Config "getUsers"
$.parseJSON( dynoData[ dyn.method ](cbk, val, dyn.display) );
});
// config AJAX
getUsers: function(cbk, val, recs){
var form = "",
pullRetailers = ( val === undefined ? "" : val ),
service = "../services/some.cfc",
method = "by",
returnformat = "json",
targetUrl = "",
formdata = "...manually_serialized...,
successHandler = function(objResponse, cbk) {
cbk( objResponse );
};
// finally pass to the generic JSON handler
ajaxFormSubmit( form, service, formdata, targetUrl, successHandler, "yes", "", returnformat, cbk );
}
// generic AJAX
var ajaxFormSubmit =
function ( form, service, formdata, targetUrl, successHandler, dataHandler, errorHandler, returnformat, type ){
...
$.ajax({
async: false,
type: type == "" ? "get" : type,
url: service,
data: formdata,
contentType: 'application/x-www-form-urlencoded',
dataType: returnformat,
success: function( objResponse ){
if (objResponse.SUCCESS == true || typeof objResponse === "string" ){
dataHandler == "yes" ? successHandler( objResponse, override ) : successHandler( override );
}
},
error: function (jqXHR, XMLHttpRequest, textStatus, errorThrown) { }
});
}
但是这对于如何防止这两个事件触发我的Ajax更新的实际问题没有多大帮助。
答案 0 :(得分:3)
我会尝试设置一个像这样的值检查函数:
var $inputIntance = $("#path-to-your-input");
var lastInputValue;
function checkInputValue () {
var newValue = $inputIntance.val();
if (newValue != lastInputValue) {
// make your AJAX call here
lastInputValue = newValue;
el = $inputIntance.closest('ul');
widget[func](dyn, el, lib_template, locale, lastInputValue, "update");
}
}
然后通过您喜欢的任何用户操作事件触发此检查:
$inputIntance.on('keyup change', function(e) {
checkInputValue();
}
或者像这样
$inputIntance.on('keyup change', checkInputValue );
<强>更新强> 可能存在每次必须限制AJAX请求数量的情况。 我在以前的代码中添加了时间控制功能。您可以在下面找到代码并直接试用here in JSFiddle。
$(document).ready(function () {
var $inputIntance = $("#test-input");
var lastInputValue;
var valueCheckTimer;
var MIN_TIME_BETWEEN_REQUESTS = 100; //100ms
var lastCheckWasAt = 0;
function checkInputValue () {
lastCheckWasAt = getTimeStamp();
var newValue = $inputIntance.val();
if (newValue != lastInputValue) {
// make your AJAX call here
lastInputValue = newValue;
$("#output").append("<p>AJAX request on " + getTimeStamp() + "</p>");
//el = $inputIntance.closest('ul');
//widget[func](dyn, el, lib_template, locale, lastInputValue, "update");
}
}
function getTimeStamp () {
return (new Date()).getTime();
}
function checkInputValueScheduled() {
if (valueCheckTimer) { // check is already planned: it will be performed in MIN_TIME_BETWEEN_REQUESTS
return;
} else { // no checks planned
if ((getTimeStamp() - lastCheckWasAt) > MIN_TIME_BETWEEN_REQUESTS) { // check was more than MIN_TIME_BETWEEN_REQUESTS ago
checkInputValue();
} else { // check was not so much time ago - schedule new check in MIN_TIME_BETWEEN_REQUESTS
valueCheckTimer = window.setTimeout(
function () {
valueCheckTimer = null;
checkInputValue();
},
MIN_TIME_BETWEEN_REQUESTS
);
}
}
}
$inputIntance.bind('keyup change', function(e) {
$("#output").append("<p>input event captured</p>");
checkInputValueScheduled();
});
});
答案 1 :(得分:1)
除了keyUp
之外,还有任何理由倾听change
吗?也许真正重要的只是其中一个事件。
如果没有,我猜你必须按照你的建议使用一个闭包。
答案 2 :(得分:1)
之前我遇到过这个问题,我最终做的是在创建时保存对象上的请求,并测试先前设置的请求以在必要时中止它。您必须编辑触发ajax调用的函数。例如:
if ( ajaxRequest ) {
ajaxRequest.abort();
}
ajaxRequest = $.ajax({ ... }); // triggers ajax request and saves it
如果widget
函数返回ajax对象,那么您可以将其分配给变量,而不是修改原始的ajax请求。
答案 3 :(得分:1)
确定。我得到了它(经过1000次尝试后......)。
这是什么工作=触发首先触发的事件,阻止预告片:
var isEven;
input.on('keyup change', function(e) {
isEven = true;
if (timer) {
window.clearTimeout(timer);
}
timer = window.setTimeout( function() {
timer = null;
val = input.val();
el = input.closest('ul');
// prevent double firing after interval passed
if (isEven === true ){
isEven = false;
} else {
isEven = true;
return;
}
widget[func](dyn, el, lib_template, locale, val, "update");
}, interval );
});
似乎应该做的事情。如果错了,请随意纠正我。
答案 4 :(得分:0)
如果首先触发一个,则删除另一个。
const handler = e => {
const eventType = e.type === 'mousedown' ? 'click' : 'mousedown';
window.removeEventListener(eventType, handler);
};
window.addEventListener('click', handler);
window.addEventListener('mousedown', handler);