堆栈在第0行溢出 [英] Stack overflow at line 0

查看:156
本文介绍了堆栈在第0行溢出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个表单验证脚本,不幸的是在崩溃之前不久返回堆栈溢出警告框(IE7)并且在IE8中直接崩溃(它确实先工作,非常慢。)

I have a form validation script that is unfortunately returning the Stack overflow at line 0 alert box shortly before crashing (IE7) and just straight up crashes in IE8 (It does work first, very slowly).

我为你的测试乐趣做了一个jsFiddle: http://jsfiddle.net/yuNXm/2/ 在输入需要验证然后失去焦点的输入值后,会发生堆栈溢出。
(电子邮件字段是ajax驱动的,所以不会在那里运行)。

I have made a jsFiddle for your testing pleasure: http://jsfiddle.net/yuNXm/2/ the stack overflow occurs after you have entered a value into an input which requires validation and then lose it's focus. (the email field is ajax driven so won't function there).

相关的Javascript:

The relevant Javascript:

jQuery(document).ready(function($) {

    var inputs = $('input[data-validation-method]');
    var fields = $();
    var classes = ['fail', 'win'];

    //Methods of validation, must return an object like so {result: [boolean], message: [string or false]} as a parameter of the callback() function;
    var methods = {

        'email' : function(field, dependancies, callback) {
            var value = field.val();
            var response = false;
            field.addClass("loading");
            $.post(
               ajaxData.url, 
               {
                  'action':'validate_form',
                  'value': value,
                  'method': field.data('method')
               }, 
               function(response){
                   return callback(response);
               }
            ).complete(function() {
                field.removeClass("loading");
            });
        },

        'password' : function(field, dependancies, callback) {
            var value = field.val();
            var response = {};
            if (value.length < 8) {
                response.result = false;
                response.message = 'Your password must be a minimum of 8 characters';
            } else {
                response.result = true;
                response.message = false;
            }
            return callback(response);
        },

        'verify_password' : function(field, dependancies, callback) {
            var value = field.val();
            var response = {};
            if (value != dependancies["password"].val()) {
                if (!dependancies["password"].val() || !value) {
                    return false;
                }
                response.result = false;
                response.message = 'Passwords do no match';
            } else {
                response.result = true;
                response.message = false;
            }
            return callback(response);
        }
    }

    // Prepare fields for validation
    inputs.each(function() {
        createField($(this));
    });

    function createField (field) {
        inputs = inputs.not(field);
        var method = field.attr('data-validation-method');
        var requires = field.attr('data-validation-requires');
        if (!!requires) {
            requires = requires.split(',');
            var dependancies = {};
            $.each(requires, function(key, value) {
                var element = $('#' + value);
                if(element.length) {
                    dependancies[element.attr('id')] = element;
                    if(inputs.find(element).length) {
                        createField(element);
                    }
                    if ($.isArray(element.data('linked_fields'))) {
                        element.data('linked_fields').push(field);
                    } else {
                        element.data('linked_fields', [field]);
                    }
                }
            });
        }
        if (methods[method]) {
            fields = fields.add('#' + field.attr('id'));
            field.data('method', method);
            field.data('dependancies', dependancies);
        }
    }

    function validate (field) {
        var callback = function(response) {
            field.data('response', response);
            if (response) {
                toggleFlag(field, 'show');
            } else {
                toggleFlag(field, 'remove');
            }
            if($.isArray(field.data('linked_fields'))) {
                $.each(field.data('linked_fields'), function(key, value) {
                    validate(value);
                });
            }
        }
        methods[field.data('method')](field, field.data('dependancies'), callback);
    }

    fields.focus(function() {
        var field = $(this);
        field.data("value", field.val());
        field.bind("propertychange keyup input paste", function(event){
            if(field.data("response") && (field.val() != field.data("value"))) {
                toggleFlag(field, "hide");
                if($.isArray(field.data('linked_fields'))) {
                    $.each(field.data('linked_fields'), function(key, value) {
                        toggleFlag(value, "hide");
                    });
                }
            }
        });
    });

    fields.blur(function() {
        var field = $(this);
        if (field.val().length) {
            if (field.val() != field.data("value")) {
                toggleFlag(field, "remove");
                validate(field);
            } else {
                toggleFlag(field, "show");
            }
        } else {
            toggleFlag(field, "remove");
        }
    });

    function toggleFlag (field, method) {
        var flag = field.data("flag");
        var response = field.data("response");
        if (response) {
            switch (method) {
                case "show":
                    if (response.message) {
                        if(!flag) {
                            flag = $('<span class="pie ' + classes[~~response.result] + '">' + response.message + '</span>').insertAfter(field);
                            field.data("flag", flag);
                            flag.hide();
                        }
                        if (!flag.data("active")) {
                            flag.data("active", true);
                            flag.stop(true, true).animate({height: "show", opacity: "show"}, 500);
                        }
                    }
                    field.addClass(classes[~~response.result]);
                    break;
                case "hide":
                    if (flag) {
                        if (flag.data("active")) {
                            flag.data("active", false);
                            flag.stop(true, true).animate({height: "hide", opacity: "hide"}, 500);
                        }
                    }
                    field.removeClass(classes[~~response.result]);
                    break;
                case "remove":
                    if (flag) {
                        field.removeData("flag");
                        if (flag.data("active")) {
                            flag.stop(true, true).animate({height: "hide", opacity: "hide"}, 100, function() {
                                flag.remove();
                            });
                        }
                    }
                    field.removeClass(classes[~~response.result]);
                    field.removeData("response");
                    break;
            }
        }
    }

});

相关HTML:

<form action="" method="post" class="user-data">
<div class="fields">
    <label for="email">Email:</label>
    <input type="text" name="email" id="email" data-validation-method="email" class="text" value="" placeholder="youremail@somesite.com" />
    <span class="info">We won\'t do anything cheeky with your email... promise.</span>
    <label for="password">Choose a password:</label>
    <input type="password" name="password" id="password" data-validation-method="password" class="text" value="" />
    <label for="verify_password">Retype your password:</label>
    <input type="password" name="verify_password" id="verify_password" class="text" data-validation-method="verify_password" data-validation-requires="password" value="" />
    <input type="checkbox" name="mailing_list" value="true" /> <label for="mailing_list">I would like to recieve email updates about new features</label>
    <span class="info">We won\'t spam your inbox, emails will be infrequent.</span>
</div>
<input type="submit" id="submitbtn" class="button omega" name="submit" value="Create your account" />
</form>

现在我知道这通常是由于递归,我在脚本的两个区域使用递归。

Now I know this is normally due to recursion, and I use recursion in two areas of the script.

重复功能1:

function createField (field) {
    inputs = inputs.not(field);
    var method = field.attr('data-validation-method');
    var requires = field.attr('data-validation-requires');
    if (!!requires) {
        requires = requires.split(',');
        var dependancies = {};
        $.each(requires, function(key, value) {
            var element = $('#' + value);
            if(element.length) {
                dependancies[element.attr('id')] = element;
                if(inputs.find(element).length) {
                    createField(element);
                }
                if ($.isArray(element.data('linked_fields'))) {
                    element.data('linked_fields').push(field);
                } else {
                    element.data('linked_fields', [field]);
                }
            }
        });
    }
    if (methods[method]) {
        fields = fields.add('#' + field.attr('id'));
        field.data('method', method);
        field.data('dependancies', dependancies);
    }
}

因为堆栈溢出仅在您与需要验证的输入, createField 函数仅用作初始化函数我不认为是这个。

Because the stack overflow occurs only when you interact with an input that needs validation, and the createField function is only used as an initialisation function I don't think it is this one.

重复功能编号2:

function validate (field) {
    var callback = function(response) {
        field.data('response', response);
        if (response) {
            toggleFlag(field, 'show');
        } else {
            toggleFlag(field, 'remove');
        }
        if($.isArray(field.data('linked_fields'))) {
            $.each(field.data('linked_fields'), function(key, value) {
                validate(value);
            });
        }
    }
    methods[field.data('method')](field, field.data('dependancies'), callback);
}

我无法访问任何其他外部程序进行调试(公司)环境),谁能引导我朝着正确的方向前进?

I don't have access to any other external programs to debug this (corporate environment), can anyone lead me in the right direction here?

推荐答案

Internet Explorer正在触发事件 propertychange 每当你使用jQuery addClass removeClass 时。问题代码在这里:

Internet Explorer is firing the event propertychange whenever you use jQuery to addClass or removeClass. The problem code is here:

     var field = $(this);
        field.data("value", field.val());
        field.bind("propertychange keyup input paste", function(event){
            if(field.data("response") && (field.val() != field.data("value"))) {
                toggleFlag(field, "hide");
                if($.isArray(field.data('linked_fields'))) {
                    $.each(field.data('linked_fields'), function(key, value) {
                        toggleFlag(value, "hide");
                    });
                }
            }
      });

toggleFlag 函数中调用jQuery的 addClass removeClass 。这创建了导致堆栈溢出的无限递归循环。

In your toggleFlag function you call jQuery's addClass and removeClass. That created the infinite recursion loop that led to the stack overflow.

如果你取出 propertychange 它的效果很好在Internet Explorer以及所有其他浏览器上。

If you take out the propertychange it works great on Internet Explorer as well as all other browsers.

工作示例: http ://jsfiddle.net/yuNXm/9/

您在Internet Explorer上遇到此问题的原因是 onpropertychange 是Microsoft为Internet Explorer实施的专有事件。它没有被其他浏览器实现。

The reason you were having this problem only on Internet Explorer is that onpropertychange is a proprietary event implemented by Microsoft for Internet Explorer. It is not implemented by other browsers.

使用IE6-8调试堆栈溢出:

将来可用于诊断这些类型的堆栈溢出的好方法是:

A good method you can use in the future to diagnose these types of stack overflows is to:


  1. 识别其中一个无限递归循环涉及的函数。如果您在没有调试功能的情况下坚持使用IE6-8,那么这需要在各种功能中发出警报,直到找到无限循环功能。

  1. Identify one of the functions involved with the infinite recursion loop. If you're stuck with IE6-8 with no debugging capability, then this entails placing alerts in various functions till you find an infinitely looping function.

放置此项函数顶部的代码行:

Place this line of code at the top of the function:

alert(arguments.callee.caller.toString());

此警报将告诉您哪个函数正在调用无限循环函数。然后通过回溯无限递归循环中涉及哪些函数,您可以隔离代码中需要仔细检查无限循环原因的部分。

This alert will tell you which function is calling the infinitely looping function. Then by tracing back which functions are involved in the infinite recursion loop, you can isolate the parts of your code you need to closely examine for the cause of the infinite loop.

当然,如果你有一个带有适当调试工具的现代网络浏览器,这不是必需的 - 你只需要逐步完成代码。

Of course if you have a modern web browser with proper debugging tools, this isn't necessary--you would just step through the code.

在附注中,我感受你的痛苦。我的工作的一部分还涉及为企业客户编写JavaScript,其中IE6-8通常是他们的IT部门强加的浏览器。没有调试工具,只有警报和评论;当您对堆栈溢出进行故障排除时,甚至不能使用行号。

On a side note, I feel your pain. Part of my job also involves coding JavaScript for corporate clients where IE6-8 is often the browser imposed by their IT Dept. No debug tools, just alerts and comments; not even a line number to work with when you're troubleshooting stack overflows.

这篇关于堆栈在第0行溢出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆