javascript - 实在是找不出问题在哪了,麻烦大家找找BUG出在哪

查看:78
本文介绍了javascript - 实在是找不出问题在哪了,麻烦大家找找BUG出在哪的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问 题

在表单验证的时候出现了如下问题:

我找到了一个办法可以解决这个问题:

将isValid的声明调到上一层作用域中,问题得到解决(这个解决办法给我的启示是好像trigger执行完毕后,isValid又被声明了一次一样,但是我调试发现重头到尾只声明了一次)

另外,只有当第一次验证失败后(即表单的输入不合法),改正表单内的值使其合法后进行第二次验证才会出现这个问题,如果是第一次就输入合法,我调试发现修改isValid的值是始终有效的。
还有,不仅是isValid,我还测试了多个变量声明在enSureCallback函数内,然后在submitHandler中修改,都是和这个一样的情况。

我已经排除了异步的情况,重复声明或者调用的情况,实在是找不出哪里有问题了。因为复现有点麻烦,依赖也有2,3个,所以在线DEMO不好编写。因此大家有任何的猜测都可以提出来,说不定都是解决问题的突破口,先表示一下感谢^_^

----------------------------------------------------2016.10.4补充----------------------------------------------

这是第一次表单输入的值就合法时的函数调用情况

这是第一次表单输入不合法,然后再输入合法时的函数调用情况

可以看到完全没有区别(包括右边调用函数的具体行数),但是BUG就是发生了。。

下面是第一次表单输入的值就合法时的详细情况,当执行了isValid = true这条语句后,我们在call stack中跳转到ensureCallback函数,可以看到值修改是成功的。

下面是第一次表单输入不合法,然后再输入合法时的详细情况,当执行了isValid = true这条语句后,我们在call stack中跳转到ensureCallback函数,可以看到值修改是不成功的。

还有虽然之前已经说了排除了异步的干扰,看到评论里有朋友还是在说这个问题,这里再说明一下,这里真的真的没有异步,是先执行的handler,再return的,而且我调试的时候开了,也没有发现任何异步函数在执行,所以真的可以排除异步的问题了。

现在我的重点思考在于1.为什么只有在第一次失败后才会出现这个BUG,第一次的验证对后面的验证到底产生了什么影响(我是真的想不出有什么影响。。)2.像我之前提到的,为什么将isValid的声明放到上一层作用域去声明就没有BUG了.

希望这次的补充能够帮助大家分析问题

解决方案

---------------------------------找到答案了,来结贴了-----------------------------------------

请教了一位朋友,指出了问题所在。主要还是JQ-validate的问题,如下图:

知道了哪里的问题,我们就知道怎么去修复了。即只需要让他的if判断一直为false,并且每次执行都释放之前绑定的事件就行了。为了以后方便维护,我们采取不改validate源码的方式,在进行validate前添加

$formWrap.data('validator')
&& ($formWrap.data('validator', null), $formWrap.off());

OK,BUG离我们远去了(但其实这种改法也并不好,因为.off要执行的操作太多了,不过以后肯定是会自己去实现一个validate库的,所以这里就不过于纠结了)。

此外,我们可以编写如下的测试用例用来重现这一问题,如下所示:


function ensureCallback() {
    var num = 2;

    var o = {
        validate:function() {
            // 第一次验证的时候我们绑定事件,以后的验证则不再绑定,正是这一点导致了bug
            if($('body').data('validator'))
                return;

            $('body').on('submit', this.submitHandler).data('validator', 1);
        },
        submitHandler:function(){
            console.log('在submitHandler内未修改num时num的值:', num);
            num++;
            console.log('在submitHandler内修改num后num的值:', num);
        }
    };

    o.validate();
    $('body').trigger('submit');
    console.log('执行完ensureCallback后num的值为:%d\n\n', num);
}

// 下面我们来模拟那个BUG,即接连两次调用

// 第一次调用模拟的是输入不合法的情况,注意第一次调用会绑定事件
ensureCallback();

// 第二次调用模拟的是输入合法的情况,注意第二次调用不会绑定事件,所以这里trigger后执行的是第一次绑定的
// 事件,所以无论再执行多少次,他都是改变的第一次绑定的事件里面对应的num,对自己的num是没有影响的
ensureCallback();

// 我们甚至可以多调用几次来印证这一点
ensureCallback();
ensureCallback();
ensureCallback();

// 其实这个和输入合法不合法并没有太大关系了,主要是事件的问题

运行结果如下:

如果你还觉得不够清晰,那么可以看下面这张按照顺序结构平铺出来的代码(这张图由那位朋友提供):

这也就很好的解释了为什么将isValid提示一个作用域声明就不会出现BUG,因为那样就能保证无论事件绑定了几次,触发的是第几次,修改的isValid始终为一个值

结语:尽管在这个BUG消耗了很多时间,不过也算是应交的学费了,借助这个问题,也更加了解了事件与闭包,以及在编写插件时应考虑到的问题,也算是小有收获了^_^

这篇关于javascript - 实在是找不出问题在哪了,麻烦大家找找BUG出在哪的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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