2015-06-16 12 views
0

上下文的功能:的Javascript異步調用到更新DOM元素重疊,造成問題

我有一個要求輸入郵編,州和城市的一種形式。在每個輸入字段旁邊,我有兩個跨度,其中一個在輸入良好時顯示綠色複選標記,另一個在輸入錯誤時顯示紅色x。當然,在任何時候只有一個可見。

<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> 

我有一個檢測輸入到zip字段,然後做一個數據庫調用從郵政編碼得到國家和城市,自動填寫表格的函數。

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

這是ajax的功能,自動填充州/城市並隱藏/顯示適當的反饋跨度。

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(); 
    } 
} 

問題:

此代碼工作,然而也有一些情況下,如果我把在郵政編碼極快的地方,無論是#ZipBad#ZipGood跨度最終會可見。以相對正常或緩慢的速度輸入會導致預期的行爲。

我認爲這與異步調用validateZip()有關,但我並不知道如何解決這個問題。有沒有人有任何想法?

+1

您需要製作新的人之前先取消先前的Ajax請求。請參閱:http://stackoverflow.com/questions/4551175/how-to-cancel-abort-jquery-ajax-request –

+0

此外,您需要刪除請求。 Debouncing有點像限速。請參閱:http://benalman.com/code/projects/jquery-throttle-debounce/examples/debounce/ –

+0

_「#ZipBad和#ZipGood跨度最終都可見」_'#ZipGood'不出現在' html','js'?如果'#ZipOK'隱藏了'keyup'事件處理函數,那麼預期的結果是什麼? – guest271314

回答

3

如果用戶鍵入的速度很快,那麼最終可能會同時出現多個動畫,而非動畫的.hide()將按錯誤的順序排列,可能會以錯誤的顯示結束。按順序的動畫隊列,.hide()不會讓事情失序。

也有一些邊緣情況下,您最終可能會同時在航班中出現多個ajax呼叫,但這需要在zip字段中鍵入5個字符,然後快速退格並再次輸入第五個字符,這可能會最終也會令人困惑。

您可以通過每一個動畫或可見性改變之前,使用.stop(true)抵禦動畫將停止任何當前正在運行的動畫,你可以通過取消以往任何呼叫這樣抵禦多種Ajax調用:


這裏的你可以實現一個方法:

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(); 
    } 
} 

僅供參考,我也參加了同樣的選擇要使用的多個項目,並使用jQuery鏈以簡化代碼的機會。

見jQuery的.abort()的討論這個其他答案Ajax調用:

Abort Ajax requests using jQuery

+0

_「如果用戶鍵入的速度很快,那麼您將同時處理多個Ajax調用。」_這是不正確的。請看'if(zip.length === 5 && $ .isNumeric(zip)){'在OP – guest271314

+1

@ guest271314 - 有一個邊緣情況可能會導致多個Ajax調用輸入5數字,然後快速點擊退格鍵那麼另一個數字。這可能不是OP所遇到的,但它也應該被防守。 – jfriend00

+0

_「有一個邊緣情況可能導致多個ajax調用鍵入5個數字,然後快速點擊backspace,然後是另一個數字」_多個ajax調用會在這裏結果? – guest271314