To jest to co się dzieje (Pseudokod):
Kiedy piszesz powoli:
.keyup1
.remove1
//asynchronous ajax1 request takes some time here...
.append1
.keyup2
.remove2
//asynchronous ajax2 request takes some time here...
.append2
Kiedy piszesz szybko:
.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
Aby rozwiązać duplikaty problemu , chciałbyś, aby twoje wyniki usuwały/dołączały operację atomową - używając .replaceWith
.
wyniki budowanie bloków HTML najpierw jako ciąg znaków, a następnie wykonaj .replaceWith
zamiast .remove
/.append
:
var result = '';
for (i in results) {
result += "<div class='result'>" + results[i].name + "</div>";
}
$("#sresults").replaceWith('<div id="sresults">' + result + '</div>');
Innym problemem (nie związane z duplikatami) może być tak, że starszy wynik nadpisuje nowszej który przybył wcześniej (ponieważ AJAX jest asynchroniczny, a serwer może wysyłać odpowiedzi nie w tej samej kolejności, w jakiej otrzymuje żądania).
Jednym ze sposobów uniknięcia tego przywiązuje udostępnia gościom Marker (rodzaj „numer seryjny”) na każde żądanie i sprawdzenie go w odpowiedzi:
//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 ...
}
});
Po stronie serwera:
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);
}
Another podejście polegałoby na zsynchronizowaniu żądań .ajax()
, ustawiając opcję async
na false
. Jednak to może tymczasowo zamknąć przeglądarkę, gdy żądanie jest aktywny (patrz docs)
A także powinno się wprowadzić limit czasu jak algiecas sugeruje, aby zmniejszyć obciążenie serwera (to trzecia kwestia, nie związane z duplikatów ani na żądanie/kolejność odpowiedzi).
Ja ha (ve) d ten sam problem! +1 – genesis
Nie powinieneś wywoływać metody .append() w pętli. Utwórz łańcuch i wywołaj funkcję .append() raz, ze względu na wydajność. Za każdym razem, gdy wywołuje się metodę .append(), parser HTML musi działać, a przeglądarka musi wykonać fragmentaryczne odświeżanie.Szybciej zrobić to raz z dużą porcją niż zrobić to często z mniejszymi porcjami. – ckruse
@ckruse thanx, zmieniłem na $ .each i wciąż ten sam problem, chociaż teraz mogę pisać trochę szybciej, nie mając go ... :) – ilyo