/ / Javascriptové asynchrónne volania na funkciu, ktorá aktualizuje prvky DOM, sa prekrývajú a spôsobujú problémy - javascript, jquery, html, ajax, formuláre

Asynchrónne volania funkcie Javascript, ktoré aktualizujú prvky DOM, sa prekrývajú a spôsobujú problémy - javascript, jquery, html, ajax, formuláre

Kontext:

Mám formulár, ktorý požaduje PSČ, štát acity. Vedľa každého vstupného poľa mám dve rozpätia, jedno, ktoré zobrazuje zelené začiarknutie, ak je vstup dobrý, a druhé, ktoré zobrazuje červené x, ak je vstup zlý. V každom okamihu je samozrejme viditeľný iba jeden.

<input type="text" id="Zip" class="form-control">
<span id="ZipOK" style="display:none;" class="glyphicon glyphicon-ok"></span>
<span id="ZipBad" style="display:none;" class="glyphicon glyphicon-remove"></span>

<input type="text" id="State">
<span id="StateOK" style="display:none;" class="glyphicon glyphicon-ok"></span>
<span id="StateBad" style="display:none;" class="glyphicon glyphicon-remove"></span>

<input type="text" id="City">
<span id="CityOK" style="display:none;" class="glyphicon glyphicon-ok"></span>
<span id="CityBad" style="display:none;" class="glyphicon glyphicon-remove"></span>

Mám funkciu, ktorá zisťuje vstup do poľa zip a potom volá databázu, aby získala štát a mesto z PSČ a automaticky vyplnila formulár.

jQuery(".form-control").keyup(function(){
validateZipcode();
});

Toto je funkcia, ktorá vykoná ajax, automaticky doplní štát / mesto a skryje / zobrazí vhodné rozpätie spätnej väzby.

function validateZip() {
zip = $("#Zip").val();
if (zip.length === 5 && $.isNumeric(zip)) {
$.ajax({
type:"POST",
url: "?report=ajax&request=getStateAndCityFromZip",
data:"Zip="+encodeURIComponent(zip),
success: function(output) {
output = $.parseJSON(output);
if (output["State"].length > 0 && output["City"].length > 0) {
$("#State").val(output["State"]);
$("#City").val(output["City"]);
$("#StateOK").fadeIn();
$("#StateBad").hide();
$("#CityOK").fadeIn();
$("#CityBad").hide();
$("#ZipOK").fadeIn();
$("#ZipBad").hide();
} else {
$("#ZipOK").hide();
$("#ZipBad").fadeIn();
}
},
error: function (xhr, ajaxOptions, thrownError) {
}});
} else {
$("#ZipOK").hide();
$("#ZipBad").fadeIn();
}
}

Problém:

Tento kód funguje tak, ako je, existujú však prípady, keď ak do zip kódu vložím veľmi rýchlo, obidva #ZipBad a #ZipGood rozpätia sa nakoniec zobrazia. Písanie relatívne normálnym alebo pomalým tempom vedie k očakávanému správaniu.

Predpokladám, že to má niečo spoločné s asynchrónnymi volaniami na validateZip (), ale neviem dosť o javascripte, aby som vedel, ako to vyriešiť. Má niekto nejaké nápady?

odpovede:

3 pre odpoveď č. 1

Ak používateľ píše rýchlo, môžete skončiť s viacerými prebiehajúcimi animáciami súčasne .hide() čo nie je animácia, pôjde v nesprávnom poradí a potenciálne skončí so zlým zobrazením. Fronta animácií v poradí, .hide() nie je to tak, že sa veci môžu dostať z postupnosti.

Existujú aj niektoré prípady, kedy by ste mohliskončí s niekoľkými volaniami ajax súčasne, ale bude to vyžadovať zadanie 5 znakov do poľa zip, rýchle opätovné rozmiestnenie a napísanie piateho znaku, čo by tiež mohlo viesť k mätúcim veciam.

Proti animáciám sa môžete brániť pomocou .stop(true) pred každou zmenou animácie alebo viditeľnosti zastavte všetky aktuálne spustené animácie a môžete sa brániť proti viacerým hovorom ajax zrušením predchádzajúcich hovorov, ako je tento:


Tu je jeden spôsob, ako by ste to mohli implementovať:

var lastValidateAjax;
function validateZip() {
var zip = $("#Zip").val();
if (zip.length === 5 && $.isNumeric(zip)) {
if (lastValidateAjax) {
lastValidateAjax.abort();
}
lastValidateAjax = $.ajax({
type:"POST",
url: "?report=ajax&request=getStateAndCityFromZip",
data: {Zip: zip},
success: function(output) {
lastValidateAjax = null;
output = $.parseJSON(output);
if (output.State.length > 0 && output.City.length > 0) {
$("#State").val(output.State);
$("#City").val(output.City);
$("#StateOK, #CityOK, #ZipOK").stop(true).fadeIn();
$("#StateBad, #CityBad, #ZipBad").stop(true).hide();
} else {
$("#ZipOK").stop(true).hide();
$("#ZipBad").stop(true).fadeIn();
}
},
error: function (xhr, ajaxOptions, thrownError) {
lastValidateAjax = null;
}
});
} else {
$("#ZipOK").stop(true).hide();
$("#ZipBad").stop(true).fadeIn();
}
}

FYI, využil som tiež príležitosť použiť viac položiek v rovnakom výbere a použiť reťazenie jQuery na zjednodušenie kódu.

Pozri túto ďalšiu odpoveď na diskusiu o jQuery .abort() pre hovory Ajax:

Zrušte Ajax požiadavky pomocou jQuery