回调中的 jQuery .remove() 调用触发无限循环
虽然我的问题本身似乎已经解决,但我希望有人能解释一下为什么会这样......
下面是同一函数的两个快照,其工作是删除包含以下内容的 div用户反馈消息。它设置为使用可选超时,如果指定了超时,它会使用 setTimeout() 调用自身,然后删除 div。
该函数的两个版本之间的唯一区别在于调用 this.remove() 的位置 - 在问题版本中,我使用 blackbirdjs 首先,然后调用 this.remove() - 执行此操作后,日志中充满了“正在删除反馈 div...”的无休止的日志消息。 “与浏览器注入它们的速度一样快。
然而,在工作版本中,我只需颠倒顺序,一切都会正常执行,一切都很好......
我很困惑,我认为这种情况下的顺序是微不足道但显然不是。谁能解释一下为什么会发生这种情况?这是 jQuery 的 bug 还是 blackbird 的问题,或者 JavaScript 的某种奇怪的怪癖?
注意:
我使用确认()调用取得了一些成功 - 如果它返回 false,我告诉它返回并且这停止了它 - 但是,仅在删除调用后添加 return 没有效果。
有趣的是,这两个版本似乎都可以在 IE8 中正常工作 - 所以这可能是 firefox/gecko 问题?
问题代码:
function clear_feedback(target_container, timeout){
log.debug("timeout: " + timeout);
log.debug("target_container: " + target_container);
if(timeout == undefined){
log.info("removing target...");
$(target_container).children(".update_feedback").slideUp("slow",
function() {
log.info("Removing feedback div...");
this.remove();
}
);
}
else{
log.info("Setting timeout, THEN removing target...");
setTimeout("clear_feedback('" + target_container + "')", timeout);
}
}
工作代码:
function clear_feedback(target_container, timeout){
log.debug("timeout: " + timeout);
log.debug("target_container: " + target_container);
if(timeout == undefined){
log.info("removing target...");
$(target_container).children(".update_feedback").slideUp("slow",
function() {
this.remove();
log.info("Removing feedback div...");
}
);
}
else{
log.info("Setting timeout, THEN removing target...");
setTimeout("clear_feedback('" + target_container + "')", timeout);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您应该检查浏览器的错误控制台,而不是仅仅依赖 blackbirdjs 控制台。
然后您会注意到浏览器错误控制台也充斥着错误消息(无论您的代码版本如何)
代码中的实际问题是
this
是回调函数中的 HTML DOM 元素,没有函数remove()
,因此子项只会被隐藏,但不会真正删除。在this.remove()
上,您会遇到异常。当回调函数抛出异常时,jQuery 会陷入无限循环,试图完成其工作。您需要做的是将元素包装在 jQuery 对象中。
现在也很清楚为什么第二个版本似乎修复了错误,
事实上 jQuery 甚至最终陷入无限循环,如果这是正确的行为是有争议的,需要对 jQuery 的内部工作进行更深入的调查。但这不是你感兴趣的
对于那些感兴趣的人,有相关的错误票
http://dev.jquery .com/ticket/2846
You should have checked your browsers error console instead of just relying on the blackbirdjs console.
Then you would have noticed that the browsers error console is flooded with error messages too (with either of your code versions)
The actual problem in your code is
this
is a HTML DOM element in the callback-function and doesn't have the functionremove()
thus the children only get hidden but not really deleted. And onthis.remove()
you get an exception. As the callback-function throws an exception jQuery ends up in an endless loop trying to do its jobWhat you need to do is wrapping the element in a jQuery object.
Now it's also clear why the second version seems to have fixed the error
The fact that jQuery even ends up in and endless loop and if this is correct behavior is debatable and needs more investigation deeper in the inner-workings of jQuery. But this isn't of interest to you
For those interested there is realted bug ticket
http://dev.jquery.com/ticket/2846
我见过这样的问题,但在不同的背景下;但是,我怀疑根本原因是相同的。
如果您查看 log.info,您会发现它将一个节点插入到 DOM 中。如果其中一个 jquery 函数恰好在正确的位置遍历 DOM,特别是在 log.info 插入节点的位置,然后如果这导致您的回调被调用,您的回调将插入另一个节点,最终陷入无限循环。
为什么在 IE8 中不会发生这种情况的问题可能是两个原因之一:要么跨浏览器的 DOM 结构不完全相同,要么 IE8 在 javascript 代码遍历 DOM 节点时使用不同的策略来处理 DOM 节点插入。树。
您可以尝试使用 Firebug,在有问题的行周围放置断点,然后查看 DOM 树以查看是否可以发现类似的行为。
I have seen an issue just like this but in a different context; however, I suspect the root cause is the same.
If you take a look at log.info, you'll see that it inserts a node into the DOM. If one of the jquery functions happens to be traversing the DOM in just the right location, in particular, right at the spot where log.info is inserting the node, and then if that causes your callback to be invoked, your callback will insert another node, and you end up in an infinite loop.
The question of why this doesn't happen in IE8 is likely to be one of two reasons: either the DOM structure isn't exactly the same across browsers, or IE8 uses a different strategy for handling DOM node insertion while javascript code is traversing the tree.
You might try using Firebug, placing a breakpoints around the problematic lines and then viewing the DOM tree to see if you can spot behavior like this.