1

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

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

该函数的两个版本之间的唯一区别是调用this.remove()的位置 - 在问题版本中,我首先使用blackbirdjs向日志发送消息,然后调用 this.remove() - 在此执行后日志被淹没与“删除反馈 div...”的无休止的日志消息一样快,浏览器可以将它们注入。

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

我很困惑,我认为这种情况下的顺序是微不足道的,但显然不是。谁能解释为什么会发生这种情况?这是一个 jQuery 错误还是 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);
    }
}
4

2 回答 2

1

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

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

您的代码中的实际问题是

this.remove();

this是回调函数中的 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 的内部工作进行更深入的调查。但这不是你感兴趣的

对于那些感兴趣的人,有 realted bug 票

http://dev.jquery.com/ticket/2846

于 2009-12-19T13:41:52.383 回答
0

我见过这样的问题,但在不同的背景下;但是,我怀疑根本原因是相同的。

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

为什么在 IE8 中不会发生这种情况的问题可能是两个原因之一:要么跨浏览器的 DOM 结构不完全相同,要么 IE8 在 javascript 代码遍历时使用不同的策略来处理 DOM 节点插入树。

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

于 2009-12-19T02:55:59.770 回答