Ajax发送单个事件

时间:2016-08-23 04:25:27

标签: jquery ajax post duplicates tomcat7

是什么原因导致ajax同时发送多个POST请求?它很难重现,因为它发生在大约2%的时间。它似乎发生在糟糕/移动网络上。我们在Android上使用Chrome。

表格如何运作

  • .keyup事件侦听器等待N个字符,然后通过ajax调用在一些次要验证后从表单发送数据。
  • 立即清除表单,以便发送另一个请求。
  • onSuccess返回并更新总计表。

问题 当系统只保存一个时,系统会保存多个记录。

我发现/尝试过的内容

  • 仅向UI返回一个调用。只有在发生这种情况时才会调用onSuccess。只要发生这种情况,用户界面就会失去同步。
  • 双击还是双击?不,我已经创建了一个检查,以防止将相同值的重复数据发送回来。
  • 服务器访问日志会在同一时间显示重复的请求。
  • 我认为这是由于HTTP / 1.1 RFC 8.2.4:它说可以重试POST请求,所以我对控制器进行了更改以检查时间戳(p),但由于请求是在同一时间,我的代码没有发现同样的p正在通过。 https://stackoverflow.com/a/14345476/2537574
  

[22 / Aug / 2016:07:14:12 -0700]" POST / api / save?p = 14718752538085 HTTP / 1.1" 200 749
  [22 / Aug / 2016:07:14:12 -0700]" POST / api / save?p = 14718752538085 HTTP / 1.1" 200 736

尝试6 - 无法正常工作

unbind / bind是一种老式的做法。现在尝试使用.off和.on并添加e.preventDefault()。 (https://stackoverflow.com/a/14469041/2537574

$(document).off('keyup', "#field").on('keyup',"#field" ,function(e) {
    e.preventDefault();
        ... 

尝试7 - 无法正常工作 return false 添加到keyup事件侦听器的末尾。

$(document).off('keyup', "#field").on('keyup',"#field" ,function(e) {
    e.preventDefault();
    // checks for 6 chars and submits
    return false;
)};

尝试8 - 去抖动

$(document).off('keyup', "#field").on('keyup',"#field" ,debounce(function(e) {
    // checks for 6 chars and submits
},50));

尝试9 - 更新了Web服务器Tomcat 更新到最新的tomcat 7.70,但没有解决问题。

当前代码

$(document).off('keyup', "#field").on('keyup',"#field" ,debounce(function(e) {

        e.preventDefault(); // attempt 6
        if(e.which != 13){
            if($(this).val().length ==6){                   
                submitForm();                   
                $(this).val('');
            }
        }
        return false; // attempt 7
    },50)); 

    function submitForm(){
        // Does some validation and if it passes calls:
        persist();
    }

    function persist(){
        var data = $("#Form").serialize();
        var persistNum = Date.now()+''+(Math.floor(Math.random() * 9)); // used to prevent duplicate insertion on POST retry

        $.ajax({
            url: "/api/save?pNum="+persistNum,
            context:document.body,
            cache: false,
            type: "POST",
            data: data,
            success:function(data, textStatus, jqXHR){},
            error: function(jqXHR, textStatus, errorThrown) 
            {}
        });     
      }

1 个答案:

答案 0 :(得分:0)

我无法确定这是你的问题,但是当你使用它来调用ajax时它绝对想要使用带有keyup的计时器,这样它只会在用户停止输入时触发。此外,我会跟踪提交状态,只有在尚未发送时才发送。这是我使用的,可以解决您的问题:

var ajaxProcessing = false; // keep track of submission state

$('#field').unbind('keyup').keyup(function(e) {
  if (ajaxProcessing) return; // if processing, ignore keyup
  var $this = $(this);
  keyupDelay(function() { // keyup timer, see below
    if (e.which != 13) {
      if ($this.val().trim().length == 6) { // good UX to trim the value here ;)
        submitForm();
      }
    }
  }, 500); // this sets it to go off .5 seconds after you stop typing. Change as needed

});

function submitForm() {
  // Does some validation and if it passes calls:
  persist();
}

function persist() {
  ajaxProcessing = true; // set is proccessing
  var data = $("#Form").serialize();
  $.ajax({
    url: "/api/save",
    context: document.body,
    cache: false,
    type: "POST",
    data: data,
    success: function(data, textStatus, jqXHR) {
      ajaxProcessing = false;
      $("#Form").find("input[type=text], textarea").val(""); // reset form here
    },
    error: function(jqXHR, textStatus, errorThrown) {
      ajaxProcessing = false;
      alert('Form was submitted. It failed though because ajax wont work from SO');
    }
  });
}



// keyup timer funtion
var keyupDelay = (function() {
  var timer = 0;
  return function(callback, ms) {
    clearTimeout(timer);
    timer = setTimeout(callback, ms);
  };
})();
input {
  width: 400px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="" id="Form">
  <input type="text" maxlength="6" placeholder="type 6 chars here then stop" id="field">
</form>