使用带有document.addEventListener的JavaScript DOMContentLoaded时,Firefox不会报告异常

时间:2011-02-18 19:04:43

标签: javascript jquery firefox

我正在编写一个没有依赖项的内部框架(即jQuery等),并且正在尝试实现自己的DOM就绪样式功能。似乎当就绪队列中的回调(在DOM上完成回调数组)时,如果在该函数内部抛出异常,执行将停止并继续到下一个回调(这就是我想要的),但Firefox不会报告错误(登录到控制台,触发错误,任何事情)。我做错了吗?

我使用Dean Edwards(http://dean.edwards.name/weblog/2009/03/callbacks-vs-events/)和jQuery源的模式组合实现了这一点。我不希望像jQuery一样实现,因为如果一个回调失败,后续的回调将不会执行。

var readyCallbacks = [];

(function () {
    var currentHandler,
    fireReady,
    removeEvents,
    loopCallbacks = function () {
        for (var i = 0, len = readyCallbacks.length; i < len; i += 1) {
            currentHandler = readyCallbacks[i];
            fireReady();
        }
    };

    if (document.addEventListener) {
        document.addEventListener('readyEvents', function () { currentHandler(); }, false);

        fireReady = function () {
            var readyEvent = document.createEvent('UIEvents');
            readyEvent.initEvent('readyEvents', false, false);
            document.dispatchEvent(readyEvent);
        };

        removeEvents = function () {
            window.removeEventListener('load', loopCallbacks, false);
            loopCallbacks();
        };

        document.addEventListener('DOMContentLoaded', removeEvents, false);
        window.addEventListener('load', loopCallbacks, false);
    } else {
        // if < IE 9
        document.documentElement.readyEvents = 0;

        document.documentElement.attachEvent('onpropertychange', function (e) {
            if (e.propertyName === 'readyEvents')
                currentHandler();
        });

        fireReady = function () {
            document.documentElement.readyEvents += 1;
        };

        removeEvents = function () {
            window.detachEvent('onload', loopCallbacks);
            loopCallbacks();
        };

        document.attachEvent('onreadystatechange', removeEvents);
        window.attachEvent('onload', loopCallbacks);
    }
})();

Client.ready = function (callback) {
    readyCallbacks.push(callback);
};

这是我的测试实现。写入控制台并且操作了DOM元素。在IE中,UNDEFINED_VARIABLE++;的错误显示在控制台中,但不在Firefox中。

<!DOCTYPE html>
<html>
<head>
    <script src="Client.js"></script>
    <script>
        Client.ready(function () {
            console.log('logging before error');
            UNDEFINED_VARIABLE++; // This does not error in Firefox
            console.log('logging after error, not logged in Firefox');
        });

        Client.ready(function () {
            console.log('before DOM access');
            document.getElementById('cheese').innerHTML = 'cheese';
            console.log('after DOM access');
        });
    </script>
</head>
<body>
<div id="cheese">test</div>
</body>
</html>

2 个答案:

答案 0 :(得分:4)

经过一些搜索后,这似乎是known Mozilla bug:在某些版本的Firefox 3.x中,未通过dispatchEvent()调度的自定义事件由处理程序抛出的错误未正确记录。这不是代码中的问题,而是浏览器实现中的问题。如果这对您来说是一个真正的问题,您可以将处理程序包装在try / catch块中以识别和处理错误:

document.addEventListener('readyEvents', function() {
    try { currentHandler() } catch (e) { console.log(e) }
}, false);

我有一个jsFiddle here,它通过一组简化的测试来演示问题。 Firefox正确记录了DOMContentLoadedload等内置事件的处理程序错误,但在为自定义事件触发处理程序时错过了错误。

答案 1 :(得分:0)

很难做到对。请参阅jQuery source code并搜索以便以便携方式查看其实施方式。请记住,您必须确保在dom准备就绪后绑定就绪处理程序时,您必须立即调用它们,否则根本不会调用它们。另请参阅this question