ExtJs异常会立即中断页面上的所有ExtJs组件

时间:2013-05-08 18:35:47

标签: javascript exception dom extjs4 rendering

如果你曾经使用过ExtJs,你可能会遇到邪恶的“无法读取属性'dom'的null”异常。对我来说,它通常发生在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组件(Tree,Grid,Button等)附加到尚未包含在DOM中的DOM元素时,会发生这种情况。通常,元素在内存中,构造为AJAX请求的一部分,准备好在成功时插入。

问题在于,当ExtJS抛出时,它从根本上打破了页面中的每个ExtJs组件。所有网格,树木,菜单,按钮都会立即被破坏。点击和悬停等事件绑定不执行任何操作或生成异常。

我目前通过首先执行document.getElementById检查来缓解此问题,如果结果未定义,则我推迟100 ms并再次尝试。这很难看,但它确实有效。这样做也很昂贵。随着某些页面变得越来越复杂,越来越多的document.getElementById延迟循环;跟踪哪个模块未测试getElementById的方法变得越来越难。

这是一团糟。

问题:有没有办法强迫ExtJS优雅地投掷?要覆盖其异常处理机制?翻转“dontBreakTheEntirePage”配置变量?

更新

在尝试direct to Sencha and after a few rebuffs之后,我更清楚地证明了这个问题(我希望):

编辑:Sencha正在审核我对original thread的回复。如果您对此类错误感兴趣,请加入讨论。

  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. 定义一个adhoc方法:

    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. 观察报告的错误:“无法读取属性'dom'为null”

  12. 现在开始在打开的标签页之间来回点击。

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

  14. 您开始在控制台中看到新的异常:“未捕获的TypeError:无法读取未定义的属性'dom'标签呈现,但在意外的位置。当前选择的选项卡并不总是正确更新。

  15. 现在,ExtJs的文档站点实际上很好地处理了这个错误。大部分页面仍以您可以应对的方式运行;但在我的场景中,我的页面已经瘫痪了。

    我们正在讨论已经呈现的内容 - 已经在DOM中。 我无法想象抛出异常的原因是为了打破已经执行过的东西。

1 个答案:

答案 0 :(得分:1)

克里斯托弗,对不起,但是Evan在你的链接帖子中对你的问题的回答都很合适并且很有意义。他完全理解你的要求,而你却不理解他。对Extjs如何构建的内在机制的进一步研究将使您意识到,在您描述它们时“已经呈现”的事物与其他与布局引擎有关的事物紧密相关。这样做是为了极大地提高渲染速度的微优化。因为它是如此紧密地联系在一起,当你试图将某些东西渲染到另一个不存在的东西时,你将把整个引擎关闭。

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

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