【问题标题】:Maximum call stack size exceeded with jQuery promise()jQuery promise() 超出了最大调用堆栈大小
【发布时间】:2017-01-22 11:25:13
【问题描述】:

我正在尝试在 jQuery 中应用简单的表单验证。如果表单字段为空,请添加类error。如果任何字段为空,请不要提交。我有以下内容:

$('#contact-form').submit(function(event) {
    event.preventDefault();

    var formValid = true;
    $('input.required, textarea.required, select.required').each(function() {
        if($(this).val() === '') {
            formValid = false;
            $(this).addClass('error');
        } else {
            $(this).removeClass('error');
        }
    }).promise().done(function() {
        if(formValid) {
            $('#contact-form').submit();
        }
    });
});

但是,当代码到达提交表单的行时,我看到了 JavaScript 错误:

未捕获的 RangeError:超出最大调用堆栈大小

【问题讨论】:

  • 我怀疑这是因为您在每个字段上都创建了一个承诺。无论如何,承诺的目的是什么?我在代码中没有看到异步操作。
  • 承诺会告诉我.each() 何时完成。
  • @Justin:不,.each() 是一个同步函数。当您到达下一行代码时,它就完成了。您不需要也不应该为此使用承诺。 (下面的答案中有更多详细信息。)

标签: javascript jquery promise


【解决方案1】:

如果表单有效,您的代码将如何运行:

  1. 提交时,阻止默认操作
  2. 检查字段
  3. 如果它们是有效的,form.submit - 这会导致提交事件,转到第 1 步

无限递归

这很简单,因为处理程序中没有异步代码

$('#contact-form').submit(function(event) {
    var formValid = true;
    $('input.required, textarea.required, select.required').each(function() {
        if($(this).val() === '') {
            formValid = false;
            $(this).addClass('error');
        } else {
            $(this).removeClass('error');
        }
    });
    if (!formValid) {
        event.preventDefault();
    }
});

【讨论】:

  • 啊,这就是问题所在。那么如何在.submit() 上绑定,然后以后可以在submit() 上不重新进入绑定呢?
  • @WillianValhakis 回答 - 虽然我不喜欢他的返回 false 而不是 preventDefault() - 那部分是错误的
  • 这很接近,但需要单击表单提交按钮两次。第一次点击不提交表单。
  • hmmm,就像在调用 submit 之前没有删除事件处理程序 - 我讨厌 jQuery 内部 - 编辑为使用 setTimeout - 总是看起来像使用它的黑客,但是 ...
  • form.submit() 周围添加setTimeout() 无效。还是要点两下。哈哈,这太荒谬了。感谢您的帮助。
【解决方案2】:

您必须验证多少个字段,为什么要与每个字段关联?检查所有字段后尝试

if(formValid) {
            $('#contact-form').submit();
        }
else return false

【讨论】:

    【解决方案3】:
    $('#contact-form').submit(function(event) {
       event.preventDefault();
       var formValid = true;
       $('input.required, textarea.required, select.required').each(function() {
          if($(this).val() === '') {
             formValid = false;
             $(this).addClass('error');
          } else {
             $(this).removeClass('error');
          }
       }).promise().done(function() {
          if(formValid) {
             $("#contact-form").off('submit').submit();
          } 
       });
       return false;
    });
    

    【讨论】:

      【解决方案4】:

      首先,.promise().done(...) 可以被清除。如前所述,没有任何异步发生。

      除此之外,实际问题很可能是提交处理程序的重复重新调用。

      尝试一个 POJS(相对于 jQuery)表单提交:

      if(formValid) {
          this.submit();
      }
      

      【讨论】:

      • 无论如何调用提交,提交处理程序仍然会被调用
      • 嗯,我学到了一些东西!我真的以为你错了:p
      • 从一开始,浏览器就以这种方式运行。尽管该行为仍然不在 W3C 推荐范围内。我还没有遇到不符合要求的浏览器。
      猜你喜欢
      • 1970-01-01
      • 2016-09-26
      • 1970-01-01
      • 1970-01-01
      • 2017-07-02
      • 2020-11-19
      • 2013-08-23
      • 2021-09-07
      • 2017-11-12
      相关资源
      最近更新 更多