Вот что происходит (псевдокод):
Когда вы печатаете медленно:
.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 предлагает снизить нагрузку на сервер ( это третья проблема, не связанная с дублированием или порядком запросов / ответов ).