【Web前端问题】实在是找不出问题在哪了,麻烦大家找找BUG出在哪

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

clipboard.png

clipboard.png

clipboard.png

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

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

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

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

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

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

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

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

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

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

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

现在我的重点思考在于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消耗了很多时间,不过也算是应交的学费了,借助这个问题,也更加了解了事件与闭包,以及在编写插件时应考虑到的问题,也算是小有收获了^_^

回答:

把isValid变量,改为最外层的全局变量试试看。

回答:

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

我觉得很有可能是被重复声明,可是我又调试不了。你的两个值出现的地方也不一样。
trigger('submit')做了什么?有可能是这步改变了变量。
在var isValid 那儿打个断点试试呢
bug嘛,慢慢调,我喜欢调bug,要是能一起调就好了,不过可以慢慢讨论,一步一步解决,我也想学习。
如果你调好了就OK了

回答:

楼主你这个应该是异步的问题吧,return isValid;始终返回的是初始值false,因为事件回调函数submitHandler中修改isValid的值那都是之后的事了,和return isValid;无关了,因为return isValid;是在主线程执行的,事件回调函数submitHandler必须等主线程执行完才会被提取调用

以上是 【Web前端问题】实在是找不出问题在哪了,麻烦大家找找BUG出在哪 的全部内容, 来源链接: utcz.com/a/142778.html

回到顶部