尝试捕获错误许多脚本组件 - JavaScript

时间:2017-03-23 12:16:05

标签: javascript jquery internet-explorer try-catch-finally

我有一个包含许多脚本组件(50+)的页面,在某些随机实例中使用IE时出现错误(在Chrome或Firefox中不会发生)。

  

“行内存不足:1”

我也做了一些谷歌搜索,这揭示了IE处理与Chrome和FF不同的问题。我想捕获此错误,并确切知道该脚本错误的原因是什么。

在那么多脚本组件上使用全局try-catch块的最佳方法是什么?所有这些脚本组件都在同一页面上。期待您的建议。

3 个答案:

答案 0 :(得分:3)

您可能希望尝试window.onerror作为起点。它需要在加载组件的<script>标记之前添加。

https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onerror

如果失败,您可以尝试将加载的组件减少一半,直到错误不再发生。然后,对页面进行概要分析(由于需要进行概要分析,您可能需要进一步减少)。寻找@Bergi建议的内存泄漏。如果实际上存在泄漏,则可能会在所有浏览器中出现,因此您也可以在Chrome中进行故障排除。

如果仍然无法产生任何有趣的内容,则问题可能出在一个特定组件中,该组件不在您加载的组件集中。理想情况下,只要包含该组件,您就会看到问题。您可以重复平分加载的组件,直到您找出罪魁祸首。

最后,忘了提及,你所有这一切的家庭基础应该是浏览器的开发者工具,例如: Chrome dev tools,或者如果它是Edge唯一的Edge debugger

而且仅供参考,Edge是崩溃的浏览器,但这并不意味着Chrome或FF中不存在此问题。

答案 1 :(得分:2)

您的问题中缺少的一件重要事情是,如果在页面加载或初始化期间发生错误,或者在浏览页面时在一段时间后发生错误

如果是在加载或初始化期间,可能是因为您的页面包含太多组件并且使用的内存比浏览器愿意接受的内存多得多(并且IE只是第一个)一个人放弃了。

在这种情况下,没有帮助,但减少页面大小。一种可能的方法是仅创建当前可见的对象(组件)(在视口中),并且一旦它们离开视口,再次从JS和DOM中删除它们(替换为空的DIV大小)到组件的大小)。

如果在浏览页面时发生错误,可能是内存泄漏造成的。您可以使用Process Explorer来查看浏览器使用的内存,并检查内存是否不断增加 - 这表明内存泄漏。

Internet Explorer中可能发生内存泄漏,因为它包含2个独立的垃圾收集器(也称为GC):一个用于DOM对象,另一个用于JS属性。其他浏览器(FF,Webkit,Chromium等;不确定Edge)只包含一个用于DOM和JS的GC。

因此,当您在DOM对象和JS对象之间创建循环引用时,IE的GC无法正确释放内存并造成内存泄漏。

var myGlobalObject;

function SetupLeak()
{
  myGlobalObject = document.getElementById("LeakDiv");
  document.getElementById("LeakDiv").expandoProperty = myGlobalObject;

  //When reference is not required anymore, make sure to release it
  myGlobalObject = null;
}

在此代码之后,LeakDiv引用似乎已被释放,但LeakDiv仍然引用其myGlobalObject中的expandoProperty,后者又引用了LeakDiv。在其他浏览器中,他们的GC可以识别这种情况并释放myGlobalObjectLeakDiv,但IE的GC不能,因为他们不知道引用的对象是否仍在使用中(因为它是GC的另一个责任。)

更不可见的是闭包创建的循环引用:

function SetupLeak()
{
    // The leak happens all at once
    AttachEvents( document.getElementById("LeakedDiv"));
}

function AttachEvents(element)
{
    //attach event to the element
    element.attachEvent("onclick", function {
            element.style.display = 'none';
    });
}

在这种情况下,LeakedDiv的{​​{1}}属性引用处理程序onclick,其关闭function属性引用element

要解决这些问题,您需要正确删除DOM对象和JS变量之间的所有引用:

LeakedDiv

您可能希望减少(或完全删除)在DOM元素上创建的闭包:

function FreeLeak()
{
    myGlobalObject = null;
    document.getElementById("LeakDiv").expandoProperty = null;
}

在这两种情况下,使用try-catch都不是选项,因为内存不足可能发生在代码中的随机位置,即使您发现下一次可能在其他地方发生的一行代码。 Process Explorer是找到内存增加时的最佳机会,并试图猜测可能导致内存的原因。

例如:如果每次打开和关闭菜单(如果有的话)都会增加内存,那么您应该看看它是如何打开和关闭的,并查找上述情况。

答案 2 :(得分:1)

您可以在调用任何组件之前和之后检查localStorage

类似的东西:

function getLocalStorage() {
    return JSON.stringify(localStorage).length;
}

function addScript(src, log) {
    if(log){
        console.log("Adding " + src + ", local storage size: " + getLocalStorage());
    }
    var s = document.createElement( 'script' );
    s.setAttribute( 'src', src );
    document.body.appendChild( s );
}

function callFunction(func, log){
    if(log){
        console.log("Calling " + func.name + ", local storage size: " + getLocalStorage());
    }
    func();
}

try {
    addScript(src1, true);
    addScript(src2, true);
    callFunction(func1, true);
    callFunction(func2, true);
}
catch(err) {
    console.log(err.message);
}

我希望它可以帮到你。再见。