快速打字时,Ajax发送“keyup”重复结果!
这是我的Ajax:
$("form[0] :text").live("keyup", function(event) { event.preventDefault(); $('.result').remove(); var serchval = $("form[0] :text").val(); if(serchval){ $.ajax({ type: "POST", url: "", data: {company : serchval}, success: function(data) { var results = (JSON.parse(data)); console.log(results); if(results[0]){ $.each(results, function(index) { console.log(results[index].name); $("#sresults").append("" + results[index].name + ""); }); } else { $("#sresults").append("לא נמצאו חברות"); } } }); } });
当我慢慢输入(慢一个字母每秒)时,我得到的结果是正确的,当我输入更快时,我得到相同结果的2倍
例:
慢打字: res1 res2 res3
快速输入: res1 res2 res3 res1 res2 res3
此外,欢迎任何改进代码的建议!
多数民众赞成在发生什么(伪代码):
当你打字慢时:
.keyup1 .remove1 //asynchronous ajax1 request takes some time here... .append1 .keyup2 .remove2 //asynchronous ajax2 request takes some time here... .append2
当您快速输入时:
.keyup1 .remove1 //asynchronous ajax1 request takes some time here... //and keyup2 happens before ajax1 is complete .keyup2 .remove2 .append1 //asynchronous ajax2 request takes some time here... .append2 //two results were appended _in a row_ - therefore duplicates
要解决重复问题 ,您可能希望使用.replaceWith
使结果删除/附加primefaces操作。
构建结果HTML首先作为字符串阻塞,然后执行.replaceWith
而不是.remove
/ .append
:
var result = ''; for (i in results) { result += "" + results[i].name + ""; } $("#sresults").replaceWith('' + result + '');
另一个问题(与重复无关)可能是较旧的结果会覆盖较早到达的较新结果 (因为AJAX是异步的,服务器可能会发出响应,而不是以接收请求的相同顺序)。
避免这种情况的一种方法是将往返标记(一种“序列号”)附加到每个请求,并在响应中检查它:
//this is global counter, you should initialize it on page load, global scope //it contains latest request "serial number" var latestRequestNumber = 0; $.ajax({ type: "POST", url: "= site_url('pages/ajax_search') ?>", //now we're incrementing latestRequestNumber and sending it along with request data: {company : serchval, requestNumber: ++latestRequestNumber}, success: function(data) { var results = (JSON.parse(data)); //server should've put "serial number" from our request to the response (see PHP example below) //if response is not latest (ie other requests were issued already) - drop it if (results.requestNumber < latestRequestNumber) return; // ... otherwise, display results from this response ... } });
在服务器端:
function ajax_search() { $response = array(); //... fill your response with searh results here ... //and copy request "serial number" into it $response['requestNumber'] = $_REQUEST['requestNumber']; echo json_encode($response); }
另一种方法是使.ajax()
请求同步,将async
选项设置为false
。 但是,这可能会在请求处于活动状态时暂时锁定浏览器(请参阅文档 )
而且你也应该引入超时,因为algiecas建议减少服务器上的负载( 这是第三个问题,与重复或请求/响应顺序无关 )。
在调用ajax之前,您应该参与一些超时。 像这样的东西应该工作:
var timeoutID; $("form[0] :text").live("keyup", function(event) { clearTimeout(timeoutID); timeoutID = setTimeout(function() { $('.result').remove(); var serchval = $("form[0] :text").val(); if(serchval){ $.ajax({ type: "POST", url: "= site_url('pages/ajax_search') ?>", data: {company : serchval}, success: function(data) { var results = (JSON.parse(data)); console.log(results); for (i in results) { console.log(results[i].id); $("#sresults").append("" + results[i].name + ""); } } }); } }, 1000); //timeout in miliseconds });
我希望这有帮助。