问题描述
我有一个搜索输入,它监听 keyup
和 change
以通过 Ajax 触发列表视图的更新.
I have a search input that listens to keyup
and change
to trigger an update of a listview via Ajax.
看起来像这样:
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 请求).
All working nice, except the handling of the timeout and binding, which causes double Ajax requests to be placed instead of a single one (when the keyup
has passed, the change
event triggers the same Ajax request again).
我可以修复"这通过添加另一个超时:
I can "fix" this by adding another timeout:
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 );
}
});
但这一点都不好……
问题:
如何确保两个都触发的绑定,我需要的函数只运行一次?
Question:
How can I make sure with two binding that both fire, that the function I need only runs once?
编辑:
Ajax 调用在这里触发:
EDIT:
The Ajax call is triggered here:
widget[func](dyn, el, lib_template, locale, val, "update");
调用该函数构建动态列表视图
which calls this function to build a dynamic listview
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 更新的实际问题并没有太大帮助.
But this does not help a lot regarding the actual question of how to prevent both events from triggering my Ajax Update.
推荐答案
我会尝试像这样设置一个值检查函数:
I would try to set up a value-checking function like this:
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");
}
}
然后通过您喜欢的任何用户操作事件触发此检查:
and then then fire this checks by any user-action event you like:
$inputIntance.on('keyup change', function(e) {
checkInputValue();
}
或者像这样
$inputIntance.on('keyup change', checkInputValue );
更新:当您必须限制每次 AJAX 请求的数量时,可能会出现这种情况.我在之前的代码中添加了时间控制功能.您可以在在JSFiddle中找到下面的代码并现场试用.
UPDATE: there might be the case when you have to limit the number of AJAX requests per time. I added time control functionality to my previous code. You can find the code below and try it live 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();
});
});
这篇关于绑定到所有在Javascript中触发的多个事件时如何运行一次函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!