【问题标题】:Adding a delay to JQuery keyup() after Ajax call在 Ajax 调用后向 JQuery keyup() 添加延迟
【发布时间】:2015-12-30 01:29:31
【问题描述】:

我遇到了一个非常棘手的问题,我不知道该如何解决。我连续有几个文本框,我需要填写这些文本框。每次填充文本框时,我都会抓取该值并进行使用该值的 Ajax 调用。响应确定该文本框是红色还是绿色(使用 Jquery css() 函数)。

现在问题来了。假设我连续有 5 个文本框。假设我输入 1-tab、2-tab、2-tab、1-tab、1-tab。这一切都非常快。例如,1-tab 表示我键入 1,然后按 Tab 按钮移动到下一个文本框。我意识到如果我走得太快,一些文本框不会更新,它们的颜色也不会改变。我认为这是由于 ajax 需要一些时间来处理。

我考虑了这个问题并想出了一个可以解决问题的想法。那就是在每次 Ajax 调用之后添加一个延迟,然后跳到下一个。我在 S.O 周围搜索,发现 this solution。但是,它并没有真正为我工作(基本上它会中断并且 JS 根本不起作用)。

这是我的 AJAX 的 sn-p。我将其剥离并删除了不必要的代码。

$( ".myTextbox" ).keyup(function() {
        //Defining my variables here

        $.ajax({    
            //Perform First Ajax request

            $.ajax({   
                //Perform Second Ajax Request
            });  

        });
});

这是我尝试使用从 S.O 找到的解决方案,但它不起作用。

var timer = null;
$( ".myTextbox" ).keyup(function() {
        clearTimeout(timer);

        timer = setTimeout(
            function(){
                .ajax({    
                //Perform First Ajax request                        
                    $.ajax({   
                        //Perform Second Ajax Request
                    });                  
                });
            }, 200);
        //Defining my variables here
});

现在,有两种选择:

  1. 关于延迟 Tab 键,我的逻辑是错误的。有没有更好的逻辑来克服我最初的问题?

  2. 我错误地使用了上面发布的解决方案。

希望能得到一些建设性的答案。

谢谢。

编辑:这是完整的代码,应要求提供。

$( ".getqty" ).keyup(function() {
    var split = this.id.split(":");
    var color = split[0];
    var size = split[1];
    var prodID = split[2];
    var $this = $(this);
    var value = $this.val();
    var stock = 0;
    var price = split[3];
    var originalProd = split[4];
    var dataStock = $this.attr("data-stock");
    if(value.length > 0){
        value = parseInt(value);
    }else{
        value = "";
    }

    $.ajax({    //create an ajax request 
        type: 'POST',
        url: 'includes/add.php',             
        dataType: 'html',   //expect html to be returned   
        data:'color='+color+'&size='+size+'&prodID='+prodID+'&qty='+value+'&originalProd='+originalProd+'&dataStock='+dataStock,     
        success: function(response){   
            if(response == "breakOut"){              
                   $this.css('background-color', '#F87171').css('border', '1px solid #B42C2C');  
                   $("#"+originalProd+"-"+color).text("Not enough in stock.").css('color', '#B42C2C');   
                   $("#"+originalProd+"-totalPrice").text("");
            }else{
                stock = response;
                if((value > 0 && value <= stock) || (value > 0 && dataStock == 'yes')){
                        $this.css('background-color', '#66CF66').css('border', '1px solid #277230');                        
                }else{
                    $this.css('background-color', '#fff').css('border', '1px solid #ccc');
                }   

                var count = 0;
                $("."+color+"-" + originalProd).each(function(){
                        if($(this).val() == 0){
                            count = count + 0;
                        }else{
                            count = count + parseFloat($(this).val(), 10);
                        }
                });

                //Single Item Total
                if(count > 0){
                    var totalPrice = (price * count).toFixed(2);
                    $("#"+originalProd+"-"+color).text(count + " - " + totalPrice.toString().replace(/\./g, ',') + " Eur").css('color', '#CCC');
                }else{
                    $("#"+originalProd+"-"+color).text("");
                }


                $.ajax({    //create an ajax request
                    type: 'POST',
                    url: 'includes/cart.php',             
                    dataType: 'html',   //expect html to be returned   
                    success: function(response){                   
                        if(response > 0){
                            $("#cart_price").text("Cart: "+response.toString().replace(/\./g, ',')+ " Eur");
                        }else{
                            $("#cart_price").text("Cart:0,00 Eur");
                        }                            
                    },
                    error:function (xhr, ajaxOptions, thrownError){
                    // alert(thrownError);
                    }
                });  
                if(pathname == 'mycart.php'){
                    location.reload();
                }                  
            }
        },
        error:function (xhr, ajaxOptions, thrownError){
         //alert(thrownError);
        }
    });

【问题讨论】:

  • 您为什么不向我们展示代码,以便我们弄清楚它为什么不起作用。听起来你可能有全局变量,每个请求都会覆盖它们。
  • @epascarello 代码很长。我用当前代码更新了它。

标签: javascript jquery ajax tabs


【解决方案1】:

您应该使用更改事件而不是 keyup。来自文档:

keyup 事件在用户释放键时发送到元素 键盘。它可以附加到任何元素,但事件只是 发送到具有焦点的元素。

当您按下 Tab 键时,您的元素将快速更改焦点,并且可能不会为具有正确值内容的输入文本触发 keyup 事件。

那就试试吧:

$( ".getqty" ).change(...)

更新: 由于更改事件只是在输入文本失去焦点时触发,因此您可以改为:

$( ".getqty" ).on('input', function() {
  var $this = $(this);
  var value = $this.val();

  if (value.length > 0) {
    value = parseInt(value);
  }
  else {
    value = "";
  }

  $.ajax({
    type: 'POST',
    url: 'data.txt',             
    dataType: 'text', 
    success: function(response){   
      $this.css('background-color', '#66CF66').css('border', '1px solid #277230');                        

      $.ajax({
        type: 'POST',
        url: 'data.txt',             
        dataType: 'text', 
        success: function(response){                   
          $("#cart_price").text("Cart: "+response.toString().replace(/\./g, ',')+ " Eur");                          
        },
        error:function (xhr, ajaxOptions, thrownError){
          console.log(thrownError);
        }
      });                 
    },
    error: function (xhr, ajaxOptions, thrownError){
     console.log(thrownError);
    }
  });
});

或者使用纯 javascript 事件监听器:

var elemList = document.getElementsByClassName('getqty');
for (var i = 0; i < elemList.length; i++) {
  elemList[i].addEventListener('input', function(e) {
    var $this = $(e.target);
    var value = $this.val();

    if (value.length > 0) {
      value = parseInt(value);
    }
    else {
      value = "";
    }

    $.ajax({
      type: 'POST',
      url: 'data.txt',             
      dataType: 'text', 
      success: function(response){   
        $this.css('background-color', '#66CF66').css('border', '1px solid #277230');                        

        $.ajax({
          type: 'POST',
          url: 'data.txt',             
          dataType: 'txt', 
          success: function(response){                   
            $("#cart_price").text("Cart: "+response.toString().replace(/\./g, ',')+ " Eur");                          
          },
          error:function (xhr, ajaxOptions, thrownError){
            console.log(thrownError);
          }
        });                 
      },
      error: function (xhr, ajaxOptions, thrownError){
       console.log(thrownError);
      }
    });
  });
}

【讨论】:

  • 这是一个不错的选择。它实际上是这样工作的。但是,除非我移动到下一个(这是change() 的点),否则当前框不会更新。因此,在这种情况下,一旦我到达最后一个文本框(来自我在 OP 中的示例),除非我单击页面上的某个位置,否则它不会对文本框进行任何更改。
  • 我没听懂。每次输入文本的值更改时都会触发更改事件。您无需更改框即可触发此事件。
  • 目前这不是正在发生的变化。每次我在文本框中输入一个值时,没有任何变化,但是当我按 Tab 键到另一个文本框时,颜色就会起作用。
  • 关键在这里:“对于选择框、复选框和单选按钮,当用户使用鼠标进行选择时,事件会立即触发,但对于其他元素类型,事件会延迟到元素失去焦点。”
  • 是的。您可以使用纯 javascript addEventListener('input' ...) 将完全按照您的需要工作。因此,一旦您进入触发函数,您就可以使用 addEventListener 并将 e.target 元素包装在一个 jquery 对象中。
【解决方案2】:

你可以试试这个来延迟keyup

$('input').keyup(function() {
    delay(function(){
      alert('Time elapsed!');
    }, 1000 );
});

【讨论】:

  • 这是否意味着“经过的时间!”需要 1 秒出现?那么,在这种情况下,假设我将所有 ajax 和变量都放在延迟中,它们会立即执行然后延迟 1 秒还是延迟 1 秒然后执行 ajax?
  • @nTuply :您可以将这个stackoverflow.com/a/1909490/5336818 用于您的ajax
  • 这是我最初尝试的。请参阅上面我的代码中的第二个 sn-p。
猜你喜欢
  • 2011-12-06
  • 2011-11-28
  • 2023-03-10
  • 1970-01-01
  • 1970-01-01
  • 2023-04-05
  • 1970-01-01
  • 2012-06-04
  • 1970-01-01
相关资源
最近更新 更多