2

如果您曾经使用过 ExtJs,那么您可能遇到过“无法读取 null 的属性 'dom'”异常。对我来说,它通常发生在 doInsert 内部(外部跟踪中 14 个堆栈中的最后一个)(ExtJs 的代码):

doInsert: function(el, o, returnElement, pos, sibling, append) {
    //<My own comment>: hint: el === null (curiously not undefined?)
    el = el.dom || Ext.getDom(el);

    var newNode;
    ...
}

当您尝试将 ExtJs 组件(树、网格、按钮等)附加到尚未在 DOM 中的 DOM 元素时,就会发生这种情况。通常元素在内存中,作为 AJAX 请求的一部分构造,准备好在成功时插入。

问题是当 ExtJS 抛出时,它从根本上破坏了页面中的每个 ExtJs 组件。所有的网格、树、菜单、按钮都会立即被破坏。像点击和悬停这样的事件绑定要么什么都不做,要么产生异常。

我目前通过首先进行 document.getElementById 检查来缓解这种情况,如果结果未定义,那么我会推迟 100 毫秒并重试。这很丑陋,但它有效。做起来也很贵。随着某些页面变得越来越复杂,document.getElementById 延迟循环越来越多;并且越来越难以追踪哪个模块内部的哪个方法没有测试getElementById。

一团糟。

问题:有什么方法可以强制 ExtJS 优雅地抛出?重写它的异常处理机制?翻转“dontBreakTheEntirePage”配置变量?

更新

在尝试直接去煎茶并经过几次拒绝之后,我更清楚地展示了这个问题(我希望):

编辑: Sencha 正在审核我对原始线程的回复。如果您对此类故障有任何兴趣,请加入讨论。

  1. 打开文档 ( http://docs.sencha.com/extjs/4.1.0/ )
  2. 打开几个选项卡(我有 Ext、Ext.tree.Panel、Ext.menu.Menu、Ext.AbstractComponent 和 Ext.draw.Color)
  3. 打开 Chrome 开发工具并查找错误。
  4. 在选项卡之间来回单击几次作为健全性检查。选项卡按预期呈现,没有错误。
  5. 现在,让我们打破页面。
  6. 回到开发工具。
  7. 切换到控制台。
  8. 定义一个临时方法:

    var tryCatch = function (func) {
    
        try {
            func.apply(this, Array.prototype.slice.call(arguments, 1));
        } catch (ex) {
            var e = {
                type: 'js',
                message: ex.message,
                detail: 'JS Error type: ' + ex.type + '<br/>\n' + 'Stack: ' + ex.stack
            };
            console.error(e);
        }
    };
    
  9. 定义一个会抛出异常的方法:

    var myExceptionFunction = function () {
        //Demo taken straight from ExtJs docs on Ext.menu.Menu
        Ext.create('Ext.menu.Menu', {
            width: 100,
            margin: '0 0 10 0',
            floating: false,
            renderTo: 'thisIdDoesNotExist', //and will break the already rendered page
            items: [{
                text: 'regular item 1'
            }, {
                text: 'regular item 2'
            }, {
                text: 'regular item 3'
            }]
        });
    };
    
  10. 在 tryCatch 包装器中执行 myExceptionFunction 方法:

    tryCatch(myExceptionFunction);
    
  11. 观察报告的错误:“Cannot read property 'dom' of null”

  12. 现在开始在打开的选项卡之间来回单击。

  13. 突然,页面出现了一些奇怪的行为。

  14. 您开始在控制台中看到新的异常:“Uncaught TypeError: Cannot read property 'dom' of undefined” 选项卡呈现,但在意想不到的地方。当前选择的选项卡并不总是正确更新。

现在,ExtJs 的文档站点实际上很好地处理了这个错误。大多数页面仍然以您可以应付的方式工作;但在我的情况下,我的页面已瘫痪。

我们谈论的是已经渲染的内容——已经在 DOM 中。我无法想象超过该点的异常会破坏已经执行的内容的原因。

4

1 回答 1

1

克里斯托弗,我很抱歉,但埃文在您的链接线程中对您的问题的回答都是适当的并且很有意义。他完全理解你的要求,而你不理解他。对如何构建 Extjs 的内部机制的进一步研究将使您意识到,正如您所描述的那样,“已经渲染”的事物与与布局引擎有关的所有其他事物都紧密相关。这样做是为了显着提高渲染速度的微优化。因为它是如此紧密地联系在一起,所以当您尝试将某些东西渲染到另一个不存在的东西时,您将关闭整个引擎。

这里的误解是您假设“已经渲染”的事物与“要渲染”的事物无关。在 extjs 中,这些东西是紧密耦合的,破坏一个会破坏另一个。由于这种紧密耦合对于使库渲染得更快是必要的(相信我,他们不能让它渲染得更慢并且仍然可以在 IE8 上使用),所以你遇到的“问题”是一个必要的邪恶。

如果您不能或不想花费开发时间在您自己的代码逻辑中实现另一个解决方案,Evan 用一个简单的 try-catch 块包围您的代码的示例是最佳途径。

于 2013-05-13T20:03:45.387 回答