【问题标题】:What would cause an ajax request to fire multiple times from a jQuery dialogue button什么会导致 ajax 请求从 jQuery 对话按钮触发多次
【发布时间】:2014-03-26 14:13:08
【问题描述】:

我有一个创建以下 html 的部分视图:

<div id="tabs-3" style="display: block;">
    <div id="My_List">
    </div>
    <button id="create-log"  role="button"> Create new Comment </button>
  <div id="dialog-log">
      <input type="hidden" value="6265" id="My_ID"/>
      <div><label>Title</label><input id="My_Title" type="text" value=""/></div>
      <div><label>Message</label><textarea id="My_Message">...</textarea></div>
   </div> 
</div>     

部分视图还会在 html 下方呈现以下脚本块。

<script>

$(function () {

    $("#dialog-log").dialog({
        autoOpen: false, modal: true, height: "auto", width: "auto", title: "Add Comments to the Log",
        position: { my: "center top", at: "center top", of: window },
        buttons: {

            "Create Comment": function () { UTIL.CreateComment($("#My_ID").val(), $('#My_Title').val(), $('#My_Message').val(), $(this)); },
            Cancel: function () { $(this).dialog("close"); }
        }
    });
    $("#create-log").button().click(function () {
        $("#dialog-log").dialog("open");
    });


});

</script>

布局视图包含一个 Utility.js 文件。它声明了一个脚本文字,便于在对话框的“创建评论”点击事件中调用 ajax。

var UTIL = {

HandleAjaxError : function (jqxhr, textStatus, errorThrown, fn) {
    switch (textStatus) {
        case "timeout": alert(fn + "\n\nStatus:server timeout"); break;
        case "error": alert(fn + "\n\nStatus:general error \nError Thrown:" + errorThrown); alert("object status: " + jqxhr.status + "\nresponse text \n>>>\n" + jqxhr.responseText + "\n<<<\n"); break;
        case "abort": alert(fn + "\n\nStatus:abort"); break;
        case "parsererror": alert(fn + "\n\nStatus:parsererror \nError Thrown:" + errorThrown); alert(jqxhr.responseText); break;
    }
    //alert(jqxhr.responseText);

},
CreateComment: function ($Id, $Title, $Message, $dlg) {

    var mydata = "ID=" + $Id + "&Title=" + $Title + "&Message=" + $Message;

    var jqxhr = $.ajax({ url: "/Log/Create/", type: "POST", dataType: "html", data: mydata

    }).done(
    function (returnhtml) {
        $('#My_List').html(returnhtml);
        $('#My_Title, #My_Message').val("");
        $dlg.dialog("close");

    }).fail(function (jqxhr, textStatus, errorThrown) { UTIL.HandleAjaxError(jqxhr, textStatus, errorThrown); })

}
}

所以在浏览器中发生的情况是,有时 - 由于我无法解释的原因 - 当用户单击对话框创建的“创建评论”按钮时会触发多个 ajax 调用。这是随机发生的,但经常发生……足以让我担心。

更重要的是,ajax 调用的重复次数各不相同——有时是 3-5,有时是 11-15 ...

我的问题与技术更相关,因为我无法以任何方式复制行为,尽管它会在生产环境中定期发生。

我需要 10 的声望才能发布截图...

【问题讨论】:

  • 我在您的代码中看不到任何会导致它多次发生的内容。尝试缩小范围。
  • 对不起,如果我完全失明,但我没有看到“创建评论”按钮。另外 - 每次弹出窗口出现时都会创建按钮吗?每次弹出窗口出现时事件都会绑定吗? “创建评论”按钮可能添加了多个点击事件。
  • @JFit 这是一个对话框按钮:"Create Comment": function () { UTIL.CreateComment 所以不,它不会被多次生成或绑定。
  • “我的问题与技术更相关,因为我无法以任何方式复制该行为,尽管它会在生产环境中定期发生。” 尝试在 IE8 标准中运行并单击真的很快。我的猜测是这只是不耐烦的用户垃圾邮件点击的情况。阻止它的一种方法是在发送 ajax 请求之前而不是之后关闭对话框。
  • 嗨,Kevin,我的直觉告诉创建对话窗口(并创建按钮)的内部 jQuery 函数将此函数绑定到点击事件“n”次......但我没有了解或测试这是否确实发生的方式。更奇怪的是,当我关闭对话框(不重新加载页面)并再次打开它时,ajax 调用只被触发一次......我错过了什么?

标签: javascript jquery jquery-ui jquery-ui-dialog


【解决方案1】:

正如 Kevin B 所指出的,问题可能只是人们不断按下按钮。

您应该在按下按钮时包含一个“发送”选项,然后禁用它。

这可以通过多种方式完成,但最简单的是设置一个标志:

CreateComment: function ($Id, $Title, $Message, $dlg) {
  // avoid multi-sending
  if($dlg.data().sending)
     return;
  $dlg.data().sending = true;

  var jqxhr = $.ajax({ url: "/Log/Create/", type: "POST", dataType: "html", data: mydata

   }).done(
    function (returnhtml) {
        // reset sending flag so in when opening the dialog again, another comment can be sent
        $dlg.data().sending = false;
        $('#My_List').html(returnhtml);
        $('#My_Title, #My_Message').val("");
        $dlg.dialog("close");

    }).fail(function (jqxhr, textStatus, errorThrown) {
      $dlg.data().sending = false;
...

这样它会检查对话框是否已经在发送数据,并且在数据实际发送之前不会运行(在完成/失败时,变量被重置)

这应该解决浏览器错误或多次点击。

【讨论】:

  • 非常感谢!我最终通过脚本文字中的属性设置标志,而不是使用对话框的 data() 因为我对操纵 DOM 以打开和关闭对话框的函数感到偏执。但真的很感谢你的建议。这让我发疯了。
  • 我做了这个方法的一个变种,它解决了我的问题 - 谢谢@Niko!重新创建问题并验证最终修复是否有效的有用工具是 Chrome 扩展 Click.Repeat:将间隔设置为 0.2 秒,然后传入要单击的按钮的 xpath。无法通过手动单击鼠标来重现问题。
猜你喜欢
  • 1970-01-01
  • 2017-08-23
  • 1970-01-01
  • 1970-01-01
  • 2019-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多