javascript中的竞争条件

时间:2012-08-07 18:01:33

标签: javascript javascript-events race-condition

在我的Web应用程序中,我为一个文本框定义了一个更改事件,该事件调用ajax方法并将文本框值存储到会话中。我有一个名为“test”的按钮,它将检查文本框中输入文本的验证,它从会话中获取字符串并验证。

<html>
<head>  
<script type="text/javascript">
$(document).ready(function(){    
    $("input", form).change(function() {
            //using ajax to store the text value to session
        });

    $("#validateAmt").click(function() {
            //using another ajax to check the value stored in session
        });
});
</script>
</head>
<body>
  <input type="text" id="amount">
  <input type="button" id="validateAmt" value="validate"/>
</body>
</html> 

但有时发生的事情是当我在文本框中输入内容而不在外面点击任何地方时,如果我直接点击“测试”按钮,其中按钮事件首先触发(在会话中使用旧值验证)和文本框更改事件触发器。所以目前我想在javascript中使用布尔标志并调用第一个文本框更改事件。对于这种情况,有没有有效或良好的解决方案?以及这些方法将如何执行?它会一个接一个地或者一个接一个地发生吗?

2 个答案:

答案 0 :(得分:1)

默认情况下,Ajax请求是异步执行的,因此您无法保证哪些请求将在何时以何时发生。 由于change应在click之前触发,并且所有javascript都在一个单独执行,您可以:

  • 使用选项$.ajax进行{ async : false }来电,但这会阻止您的来电

  • 您可以跟踪正在运行的Ajax查询,并在上一个ajax查询完成时执行剩余的ajax查询

以下是保持异步行为的可能解决方案:

​Service=new function(){
  var onGoingAjax = null;
  var onComplete = null;

  this.change = function () {
    // Cancel previous call
    if (onGoingAjax) onGoingAjax.abort();
    // Run the new Ajax call
    onGoingAjax = $ajax( { /* options */ });
    onGoingAjax.done( function() {
      // mark the ajax call as finished
      onGoingAjax=null;
      // process the second call (if any)
      processComplete();
    });
  };

  this.click = function (){
    endFunc = function() { $ajax( { /* options */ }); };
    processComplete();
  };

  function processComplete()
  {
    // check if ajax still executing => the skip this call
    if (onGoingAjax != null) return;
    // check if a complete function is set => call it
    if (onComplete) onComplete();
    // reset the complete function
    onComplete = null;
  };
}()​;

$(document).ready(function(){
  $("input", form).change(Service.change);
  $("#validateAmt").click(Service.click); 
});

答案 1 :(得分:0)

在其他事情发生之前,不要总是依赖变化事件。只需在发送到服务器之前始终验证您的数据(并始终在服务器上进行验证)。

如果验证很昂贵(例如需要ajax调用),那么你可以添加一个优化来跟踪特定值是否已经过验证,但这只是一个性能优化,而不是你的核心逻辑的一部分