2015-06-16 11 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