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ď č. 1Ak 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