• Ext JS 6应用程序Build后出现“c is not a constructor return new c(a[0])”的处理


    概述

    在对Ext JS 6的应用程序打包后,时不时会出现以下错误:

    QQ图片20160224095156

    由于是压缩后出现的错误,要进行调试也无从下手,因而这个错误会令新手手足无措,不知道是怎么回事。

    错误原因

    造成该错误的主要原因是要创建的类在打包时没有包含在包内,又或者是类名错误造成的。我遇到的一个比较典型的错误就是在requires中使用了Ext.MessageBox而不是Ext.window.MessageBox,就会出现该错误。

    解决办法

    虽然知道该错误是由于类名造成的,但苦于无法知道是那个文件中的requires出现的问题,因而要解决这个问题也很棘手,不过主要有足够耐心,还是能解决的。

    该错误出现的地方是在应用程序extpackagescoresrcclass目录下的ClassManager.js文件中的getInstantiator方法内,代码如下:

    getInstantiator: function(length) {
        var instantiators = this.instantiators,
            instantiator,
            i,
            args;
    
        instantiator = instantiators[length];
    
        if (!instantiator) {
            i = length;
            args = [];
    
            for (i = 0; i < length; i++) {
                args.push('a[' + i + ']');
            }
    
            instantiator = instantiators[length] = new Function('c', 'a', 'return new c(' + args.join(',') + ')');
            //<debug>
            instantiator.name = "Ext.create" + length;
            //</debug>
        }
    
        return instantiator;
    },

    错误中的代码就是由“instantiator=”这句代码(文件的895行)自动生成的。这段代码的主要作用是创建一个新的类实例并返回该实例,而当该类不存在或类名错误的时候,因为创建不了类的实例,就会出现错误。

    出现问题的地方已经找到,但要解决问题,不能在这里,因为在该函数内要查找是那个类出现错误,也很困难,因为调用该类的时候传递给该类的可能是一个空的类名,因而,需要在调用该方法时去查。

    通过在ClassManager.js文件中搜索getInstantiator,会发现在create方法内调用了该方法,代码如下:

    create: function () {
        var name = arguments[0],
            nameType = typeof name,
            args = arraySlice.call(arguments, 1),
            cls;
    
        if (nameType === 'function') {
            cls = name;
        } else {
            if (nameType !== 'string' && args.length === 0) {
                args = [name];
                if (!(name = name.xclass)) {
                    name = args[0].xtype;
                    if (name) {
                        name = 'widget.' + name;
                    }
                }
            }
    
            //<debug>
            if (typeof name !== 'string' || name.length < 1) {
                throw new Error("[Ext.create] Invalid class name or alias '" + name +
                                "' specified, must be a non-empty string");
            }
            //</debug>
    
            name = Manager.resolveName(name);
            cls = Manager.get(name);
        }
    
        // Still not existing at this point, try to load it via synchronous mode as the last resort
        if (!cls) {
            //<debug>
            //<if nonBrowser>
            !isNonBrowser &&
            //</if>
            Ext.log.warn("[Ext.Loader] Synchronously loading '" + name + "'; consider adding " +
                 "Ext.require('" + name + "') above Ext.onReady");
            //</debug>
    
            Ext.syncRequire(name);
    
            cls = Manager.get(name);
        }
    
        //<debug>
        if (!cls) {
            throw new Error("[Ext.create] Unrecognized class name / alias: " + name);
        }
    
        if (typeof cls !== 'function') {
            throw new Error("[Ext.create] Singleton '" + name + "' cannot be instantiated.");
        }
        //</debug>
    
        return Manager.getInstantiator(args.length)(cls, args);
    },

    注意最后一句,可以看到调用getInstantiator方法,传递了两个参数,而第一参数,根据上面的代码可知道这就是类名或类自身,这时候,一般通过在return语句上面添加“console.log(cls)”就可知道是那个类出现问题了。

    特殊情况是cls为空的时候,就不知道错误出在哪里了。这时候,就需要在return语句前添加debugger语句,在调用该方法时,在浏览器进入调试状态来查了。其实这是一个很烦人的过程,因为类的创建过程都会调用该方法,因而这个需要耐心,一直等到错误出现的时候。而且这个过程可能要重复一次才行,因为错误是在debugger后产生,你需要记录的是这个错误是在什么时候产生,这个很重要。

    当知道错误是在什么时候发生了,就可以在debugger进入调试状态的时候,在浏览器的调试工具中,查看栈信息,以确定那个类调用了该方法造成的错误,从而知道错误是产生在那个类。知道了错误在那个类,就好办了,用排除法就可以很容易知道是那个地方出问题了。

    以上步骤修改代码后,都要build一次再调试。

    由于该错误一时很难还原,栈调试无法以图片显示,在此深表遗憾,如果有需要,可加群391747779进行咨询。

    BTY:貌似在最新版的Sencha CMD中已消除了该错误。

  • 相关阅读:
    Java结束线程的三种方法(爱奇艺面试)
    Threadlocal 传递参数(百度二面)
    数据一致性 kafka 是保存副本 leader读写,follower 只备份 而 zookeeper是 leader 读写,follower负责读
    Mysql 间隙锁原理,以及Repeatable Read隔离级别下可以防止幻读原理(百度)
    SOA,SOAP,RPC,以及 RPC协议与 REST 协议之间的关系(搜狗)
    select、poll、epoll之间的区别(搜狗面试)
    windows日志查看-非法关机判断方法
    望帝春心托杜鹃 中望帝的由来~
    深入解读Quartz的原理
    Hibernate性能优化之EHCache缓存
  • 原文地址:https://www.cnblogs.com/hainange/p/6334109.html
Copyright © 2020-2023  润新知