angularjs和requirejs中“Q”和“q”之间的差异

时间:2013-08-19 19:27:16

标签: javascript angularjs requirejs breeze q

我正在创建一个基于AngularJS,Breeze和RequireJS的单页面应用程序。在使用requirejs设置AMD以使用Angular和Breeze时,我遇到了Breeze依赖于“q”的问题。如果“q”的配置规则是小写,即使“shim”中没有显式导出,Breeze也会出现此错误:

Uncaught Error: Unable to initialize Q. See https://github.com/kriskowal/q
"http://localhost:1498/Scripts/shared/breeze.js"breeze.js:1`

当require config将所有引用从“q”更改为“Q”(即使没有导出),代码也可以。有谁知道为什么会这样?

这是工作需要配置:

require.config({
    baseUrl: '../Scripts',
    paths: {
        angular: 'shared/angular',
        bootstrap: 'shared/ui-bootstrap',
        dropdowns: 'app/directives/dropdowns',
        employeeApp: 'app/modules/employeeModule',
        controllers: 'app/controllers',
        dates: 'app/directives/dates',
        jquery: 'shared/jquery',
        Q: 'shared/q',
        breeze: 'shared/breeze',
        config: 'app/services/config',
        model: 'app/services/model',
        dataservice: 'app/services/dataservice',
        expenseInfo: 'app/services/expenseInfo'
    },
    shim: {
        'angular': { 'exports': 'angular' },
        'bootstrap': { deps: ['angular'] },
        //'q': { 'exports': 'q' },
        'breeze': { deps: ['Q', 'jquery'], 'exports': 'breeze' }
    },
    priority: [ 'angular', 'bootstrap', 'dropdowns', 'jquery',
                'Q', 'breeze', 'employeeSearch', 'dates' ]
});

2 个答案:

答案 0 :(得分:2)

技术原因是微风明确地寻找“Q”。要查找所有微风,需要在源中搜索“requireLib”(不是整个单词)。

Breeze总是首先寻找全球,因为q的全局是'Q',这是微风搜索的内容

更多背景(是的,我最近遇到了一些Breeze + RequireJS的痛苦)

幸运的是,您只需更改require路径即可。然而,淘汰+ Durandal这不起作用。 Breeze需要'ko',但Durandal需要'淘汰'。解决方法是使用RequireJS map:

map: {
    //knockout used by Durandal, ko used by breeze  --> anytime ko is requested, substitute knockout
    '*': { 'ko': 'knockout' }
}

Breeze确实遇到了一些RequireJS依赖项问题,因为它没有预定义它的依赖项(在其define调用中没有列出依赖项)。这可能是因为它的一些依赖项是可配置的(你不想淘汰,但我确实如此)。这就是为什么你需要垫片来确保在Breeze请求它们之前加载它们。

jQuery有不寻常的AMD行为。大多数库在运行时都会查找AMD库。如果他们找到一个AMD库(例如RequireJS),他们会将自己加载到它(例如define(...)),并跳过将自己加载为全局。如果可以的话,jQuery会两者(出于好的理由)。这意味着Breeze总是看到并加载全局jQuery,因此无需从Breeze的'jQuery'创建一个映射到RequireJS的'jquery'。

BTW“即使没有出口”也无关紧要。垫片中的导出属性用于:加载后,使用全局“breeze”作为模块值。没有意义,因为微风看到RequireJS,将其自身加载到它而不是全局,而shim忽略了导出。

答案 1 :(得分:0)

虽然可以通过requireJs加载所有模块,但是我的第一个回答是我发现了一些困难,这对我来说太麻烦了。

如果您打算使用requireJs optomize(rjs)和almond来提供带有杏仁缩减AMD加载器的组合js文件,那么您会发现某些库存在错误。特别是我遇到了Breeze的问题,& Toastr。

optomizer期望明确定义具有明确命名的依赖项的定义语句。 Breeze使用变量依赖名称,因为它在需要时加载它们 - 因为它的依赖项是在运行时配置的。

另一个问题是使用CDN文件。 Almond不处理任何网络文件,因此必须预先加载它们。 jQuery是CDN的主要候选者,但它是包括微风在内的许多模块的必需品。并且优化垫片不能取决于任何CDN文件。

我的解决方案

我使用自己的补丁https://github.com/CodeSeven/toastr/issues/135修复了Toastr以进行优化。

但是因为修复Breeze会很麻烦我回去通过捆绑预加载它。我还添加了任何我认为可以从CDN采购的图书馆。

我通过ASP.Net捆绑包加载了breeze(及其先决条件)和CDN文件 然后在main.js

中的requirejs.config之前为requireJs定义它们

要在我的生产代码中使用这些预定义的预加载,我使用optomize的空配置我的weyland-config.js。

                'jquery':               'empty:',
                'knockout':             'empty:',
                'Q':                    'empty:',
                'breeze':               'empty:',

HTH