在不重复代码的情况下,为不同的Dojo版本声明不同的类?

时间:2014-07-03 07:04:09

标签: javascript dojo ibm-connections

我有一个为IBM Connections设计的iWidget,我的javascript代码依赖于Dojo(在Connections中默认包含)。
它目前在Connections 4.0和4.5中有效,但在Connections 5.0(上周发布)中已经破解,因为Dojo已更新到v1.9并抱怨我使用dojo.require

当我的窗口小部件尝试加载Connections 5.0时,这些消息显示在浏览器控制台中:

Avoid calling dojo.require() to load classes at runtime, use net.jazz.ajax.xdloader.load_async() instead. Function '(anonymous)' required class 'dojox.atom.io.model'.
Avoid calling dojo.require() to load classes at runtime, use net.jazz.ajax.xdloader.load_async() instead. Function '(anonymous)' required class 'dojox.atom.io.Connection'.

我想制作条件代码,使用不同的方法来定义我的widget类,并根据Dojo版本需要其他Dojo模块。

小部件javascript目前看起来像这样:

dojo.provide('insightCommunityWidgetClass');
dojo.require('dojox.atom.io.model');
dojo.require('dojox.atom.io.Connection');

dojo.declare('insightCommunityWidgetClass',null,{
    // Class fields and methods. Currently 680 lines uncompressed.
});

我还没有创建一个适用于Dojo 1.9 / Connections 5.0的版本,但我认为它看起来像这样(我必须使我的javascript文件名与所需的类名匹配):

define(['dojo/_base/declare','dojox.atom.io.model','dojox.atom.io.Connection'], function(declare){
    return declare(null, {
        // Class fields and methods.
    });
});

如何在一个文件中同时使用这两个文件并在不重复类主体的情况下进行选择?

更新
我尝试了一些条件代码,按照Dimitri的建议检查(define && define.amd),在Connections 4.0和4.5上测试了这个,并且我的行为非常奇怪。

暂时忽略任何不重复我的类的尝试,这里是一些我完全按照所示使用的条件代码,并且窗口小部件严重减少:

if (define && define.amd) {
    console.log('Declaring insightWidgetClass with AMD (new method).');
    define(['dojo/_base/declare','dojox/atom/io/model','dojox/atom/io/Connection'],
        function(declare){
            return declare(null,{
                SVC_INV: 1,
                onLoad: function() {
                    console.log('insightWidgetClass onLoad.');
                }
            });
        }
    );

} else {
    console.log('Declaring insightWidgetClass with dojo.declare (old method).');
    dojo.provide('insightWidgetClass');
    dojo.require('dojox.atom.io.model');
    dojo.require('dojox.atom.io.Connection');

    dojo.declare('insightWidgetClass',null,{
        SVC_INV: 1,
        onLoad: function() {
            console.log('insightWidgetClass onLoad.');
        }
    });
}

这似乎根本不会发生。我的console.log消息都没有出现在浏览器控制台中。

如果我注释掉条件并使其成为唯一的活动代码是else之后的块,它就会运行。我得到了“声明......(旧方法)”和“insightWidgetClass onLoad”控制台消息。

我想可能在任何类型的块中包含Dojo providerequiredeclare调用可能会导致问题,因此我测试了将工作代码放入{{1阻止,它仍然有效。

此时我尝试过的最后一件事是在其他所有内容之前添加这一行,以查看if (true) {是什么:

define

......打破了它。我的代码根本没有控制台消息 然后我从该新行中删除console.log('dojo define',define);参数,因此它只向控制台发送一个字符串,代码再次起作用。
似乎任何提及define标识符会默默地阻止其余代码运行。
控制台中没有指示问题的错误或警告。我能说的就是:WTF?!

现在回到检查define

2 个答案:

答案 0 :(得分:4)

通常两者都应该有效,dojo.provide()dojo.require()已弃用,但未完全删除。只需确保以同步模式加载dojo。

除此之外,在Dojo 1.7中引入了AMD编码方式,这意味着它也应该在IBM Connections 4.5上得到支持(尽管我不了解IBM Connections 4)。

但是如果你真的想要使用这两个代码库,你可以简单地引用同一个对象而不是复制它,例如:

var myModule = {
    // Class fields and methods.
};
if (dojo.version.major == 1 && dojo.version.minor == 9) {
    define(['dojo/_base/declare','dojox.atom.io.model','dojox.atom.io.Connection'], function(declare){
        return declare(null, myModule);
    });
} else {
    dojo.provide('insightCommunityWidgetClass');
    dojo.require('dojox.atom.io.model');
    dojo.require('dojox.atom.io.Connection');

    dojo.declare('insightCommunityWidgetClass',null, myModule);  
}

或者您可以使用以下检查:

if (typeof define === 'function' && define.amd) {
    // AMD style code
} else {
    // Non-AMD style code
}

这是大多数交叉加载程序库使用的方法。既可以在AMD加载器(Dojo,Require.js)上运行的库,也可以在Node.js上运行,或者只使用全局命名空间,它们使用类似的代码来确定它们如何加载模块。

答案 1 :(得分:2)

这不是你的代码,它应该按原样运行。我们最近遇到了同样的问题并确定了原因。

Connections 5使用的是AMD版本的Jazz框架,它提供了自己的dojo加载器。此框架用于将所需的dojo模块聚合到单个JS文件中,该文件限制了对服务器的请求数。不幸的是,这个加载器不再处理同步模块加载。当dojo.require()请求聚合器尚未加载的模块时,它会报告您报告的警告。如果模块已经加载,因为它是Jazz聚合文件的一部分,那么它可以工作。它解释了为什么你可以dojo.require()一些模块,但不是所有模块。

- >解决方法是部署服务器端OSGi包以获取所需的模块,这些模块是聚合JS文件的一部分。这有一个记录的扩展点。这可以在提高页面性能的同时解锁您。

现在,我们向IBM支持人员开放了PMR。开发团队正在制定一项决议。我们希望他们能尽快提供解决方案。

我们报告了以下问题:

  • dojo.require()
  • dojo.requireLocalization()
  • dojo.registerModulePath()/需要({路径:})

如果您考虑其他事情,请告诉我。