那是发生了什么(伪):
当你打字慢:
.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
。
生成结果HTML块首先作为字符串,然后做的.replaceWith
代替.remove
/.append
:
var result = '';
for (i in results) {
result += "<div class='result'>" + results[i].name + "</div>";
}
$("#sresults").replaceWith('<div id="sresults">' + result + '</div>');
另一个问题(不涉及重复)可以是旧的结果将覆盖其先期抵达新(因为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 (i.e. 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
。然而,这可能会暂时锁定浏览器,同时请求被激活(见docs)
同时也可作为algiecas建议,以减少服务器负载你一定要引入超时(这是第三个问题,不涉及重复,也不要求/响应订单)。
来源
2011-07-13 12:25:49
lxa
我哈(ve)d同样的问题! +1 – genesis
您不应在循环中调用.append()。出于性能原因,创建一个字符串并调用.append()一次。每次调用.append()时,HTML解析器都必须工作,并且浏览器必须进行分区重绘。这样做比较快,一次只能用较大的块进行,而不能用较小的块进行。 – ckruse
@ckruse thanx,我切换到$。每个仍然是同样的问题,虽然现在我可以输入一点速度没有它... :) – ilyo