回调中的jQuery.remove()调用触发无限循环

回调中的jQuery.remove()调用触发无限循环,jquery,firefox,infinite-loop,Jquery,Firefox,Infinite Loop,虽然我的问题似乎已经解决了,但我希望有人能解释一下为什么会这样 下面是同一函数的两个快照,其任务是删除包含用户反馈消息的div。设置为使用可选超时,如果指定了超时,则使用setTimeout()调用自身,然后删除div 函数的两个版本之间的唯一区别是调用了this.remove()——在问题版本中,我首先使用发送消息到日志,然后调用此.remove()——执行此操作后,日志中充斥着“Removing feedback div…”的无休止的日志消息浏览器可以以最快的速度将它们输入 然而,在工作版本

虽然我的问题似乎已经解决了,但我希望有人能解释一下为什么会这样

下面是同一函数的两个快照,其任务是删除包含用户反馈消息的div。设置为使用可选超时,如果指定了超时,则使用setTimeout()调用自身,然后删除div

函数的两个版本之间的唯一区别是调用了this.remove()——在问题版本中,我首先使用发送消息到日志,然后调用此.remove()——执行此操作后,日志中充斥着“Removing feedback div…”的无休止的日志消息浏览器可以以最快的速度将它们输入

然而,在工作版本中,我只是简单地颠倒顺序,一切正常执行,一切都很好

我很困惑,我会认为在这种情况下的顺序是微不足道的,但显然不是。有人能解释一下为什么会发生这种情况吗?这是jQuery的一个bug,还是blackbird的一个问题,还是JavaScript的某种奇怪的怪癖

注意:
我通过调用confirm()获得了一些混合的成功-如果它返回false,我告诉它返回,这样就停止了它-但是,在remove调用之后添加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);
    }
}
工作代码:

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);
    }
}

我看到过这样一个问题,但背景不同;然而,我怀疑根本原因是相同的

如果查看log.info,您将看到它将一个节点插入到DOM中。如果其中一个jquery函数恰好在正确的位置(特别是在log.info插入节点的位置)遍历DOM,然后如果这导致调用回调,那么回调将插入另一个节点,最终进入无限循环

为什么IE8中不会出现这种情况,这可能是两个原因之一:不同浏览器的DOM结构不完全相同,或者当javascript代码遍历树时,IE8使用不同的策略来处理DOM节点插入


您可以尝试使用Firebug,在有问题的行周围放置一个断点,然后查看DOM树,看看是否可以发现这样的行为。

我在不同的上下文中看到过类似的问题;然而,我怀疑根本原因是相同的

如果查看log.info,您将看到它将一个节点插入到DOM中。如果其中一个jquery函数恰好在正确的位置(特别是在log.info插入节点的位置)遍历DOM,然后如果这导致调用回调,那么回调将插入另一个节点,最终进入无限循环

为什么IE8中不会出现这种情况,这可能是两个原因之一:不同浏览器的DOM结构不完全相同,或者当javascript代码遍历树时,IE8使用不同的策略来处理DOM节点插入


您可以尝试使用Firebug,在有问题的行周围放置一个断点,然后查看DOM树,看看是否可以发现这样的行为。

您应该检查浏览器的错误控制台,而不是仅仅依赖blackbirdjs控制台

然后,您会注意到浏览器错误控制台中也充斥着错误消息(使用您的任一代码版本)

代码中的实际问题是

this.remove();
是回调函数中的HTML DOM元素,没有函数
remove()
,因此子项只会被隐藏,而不会被真正删除。在
this.remove()
上,您会得到一个异常。当回调函数抛出一个异常时,jQuery就陷入了一个无休止的循环,试图完成它的工作

您需要做的是将元素包装到jQuery对象中

$(this).remove();

现在也很清楚为什么第二个版本似乎已经修复了错误

log.info("Removing feedback div..."); //error logged
this.remove();  //exception

this.remove();  //exception
//log line not executed as previous line threw exception
log.info("Removing feedback div...");

事实上,jQuery甚至会以无限循环结束,如果这是正确的行为,这是有争议的,需要对jQuery的内部工作进行更深入的研究。但你对此不感兴趣

对于那些感兴趣的人,有一张不动产的虫子票


您应该检查浏览器错误控制台,而不是仅仅依赖blackbirdjs控制台

然后,您会注意到浏览器错误控制台中也充斥着错误消息(使用您的任一代码版本)

代码中的实际问题是

this.remove();
是回调函数中的HTML DOM元素,没有函数
remove()
,因此子项只会被隐藏,而不会被真正删除。在
this.remove()
上,您会得到一个异常。当回调函数抛出一个异常时,jQuery就陷入了一个无休止的循环,试图完成它的工作

您需要做的是将元素包装到jQuery对象中

$(this).remove();

现在也很清楚为什么第二个版本似乎已经修复了错误

log.info("Removing feedback div..."); //error logged
this.remove();  //exception

this.remove();  //exception
//log line not executed as previous line threw exception
log.info("Removing feedback div...");

事实上,jQuery甚至会以无限循环结束,如果这是正确的行为,这是有争议的,需要对jQuery的内部工作进行更深入的研究。但你对此不感兴趣

对于那些感兴趣的人,有一张不动产的虫子票


酷-谢谢你提供的信息-我会调查并让你知道我发现了什么。酷-谢谢你提供的信息-我会调查并让你知道我发现了什么,如果发现了什么。嘎..../head slam on desk我还没有机会测试这个,可能下一段时间不会(我从周五开始休年假过圣诞节),但读了这篇文章后,错误似乎很明显……新手犯了错误。很抱歉,时间太长了