使用RequireJS和AngularJS与OpenLayers的结合

4

我想让一个同时使用AngularJS和RequireJS的应用程序运行起来。在这个设置中,我遇到了让我的OpenLayers库工作的问题。

我在main.js中设置了主要的AMD模块:

require.config(
    {
        baseUrl: 'scripts',
        paths: {
            // Vendor modules
            angular: 'vendor/angular/angular',
            openLayers: 'vendor/openlayers-debug',
            other modules.....
        },
        shim: {
            angular: {
                exports: 'angular'
            },
            openLayers: {
                exports: 'OpenLayers'
            },
            other modules....
        }
    }
);

require(['openLayers',
        'angular',
        'app',
        'controllers/olMapController',
        'directives/olMap',
        other modules...
    ], function(OpenLayers) {
        return OpenLayers;
    }
);

然后在我用于初始化OpenLayers的Angular控制器中,我尝试指定openlayers-debug.js是一个依赖项:

define(['openLayers'],
    function(OpenLayers) {
        controllers.controller('olMapController', ['$scope', function(scope) {
            console.log('Loaded olMapController. OpenLayers version: ' + OpenLayers.VERSION_NUMBER);
        }]);
    }
);

这好像不起作用。有时候olMapController函数会被执行,但大多数情况下不会。控制台则显示错误信息:

错误:[ng:areq] 参数'olMapController'不是一个函数,而是未定义的

所以,我想OpenLayers还没有完成加载,但一些require却认为它已经加载完了,并继续加载依赖于OpenLayers的代码,例如olMapController。然后它找不到它的依赖项,于是Angular返回此错误消息。或者什么类似的东西...? 有时会发生某些事情,使得OpenLayers快速加载到它作为依赖项时已经存在。我无法确定那是什么。

我省略了其他库和模块需要和定义,为了让代码易读。希望这个例子还是可理解的。

您有什么想法可以使openlayers加载正常吗?当我将['openLayers']依赖项从olMapController中删除时,错误消息消失了。

感谢您的任何帮助。

最好的问候, Martijn Senden


你展示的错误并不意味着 OpenLayers 尚未加载。它表明任何试图使用 olMapController 的代码都是在其定义之前尝试使用它。可能是在 'directives/olMap' 中的某些代码? - Louis
我提供的示例代码中的控制器仅需要OpenLayers。在我的真实应用程序中,它需要更多。当我从中删除OpenLayers依赖项时,错误消失了。这就是为什么我认为OpenLayers尚未加载的原因。olMap指令并不会过度使用。它使用控制器中定义的类创建一个新的OpenLayers地图。 - Martijn
2个回答

6

作为参考,这是我的最终解决方案。评论angabriel提供,使我朝着正确的方向前进。

就像我说的那样,我正在使用RequireJS提供的domReady模块来引导Angular。这仍然被过早地调用,因为当angular启动时OpenLayers尚未加载。RequireJS还提供了require.config中的回调属性。这是一个在所有依赖项加载完成时触发的函数。所以我使用该函数来要求angular引导模块。现在我的配置看起来像这样:

require.config(
    {
        baseUrl: 'scripts',
        paths: {
            // Vendor modules
            angular: 'vendor/angular/angular',
            domReady: 'vendor/domReady',
            openLayers: 'vendor/openlayers-debug',
            etcetera....

        },
        shim: {
            angular: {
                deps: ['jquery'],
                exports: 'angular'
            },
            openLayers: {
                exports: 'OpenLayers'
            },
        },
        deps: ['angular',
            'openLayers',
            'app',
            'domReady',
            'controllers/rootController',
            'controllers/olMapController',
            'directives/olMap'
        ],
        callback: function() {
            require(['bootstrap']);
        }
    }
);

而bootstrap模块看起来像这样:

define(['angular', 'domReady', 'app'], function(angular, domReady) {
    domReady(function() {
        angular.bootstrap(document, ['GRVP']);
    });
});

感谢您的帮助。@angabriel: 我已经赞同了您的评论。不可能将评论作为答案接受,是吗?您最初的回答并不是我问题的答案,但是您的评论帮了我很多... 问候,Martijn

1
谢谢你,很棒你发布了解决方案。我将那个有用的评论添加到我的答案中,希望你可以给它点个赞;)。 - angabriel

4

很抱歉,由于您的代码太大而无法提供小型示例,我建议编写一个指令,利用 head.js 在特定上下文中加载所需库。也可以考虑编写一个指令来初始化 openLayers

我想您的错误是时间问题,因为 require.jsangular.js 模块加载不同步 - 更准确地说,它们之间似乎没有任何同步。

更新
重复我的评论,最终帮助引导 OP 走向正确方向:

您必须决定哪个框架起主导作用。如果使用 requireJS,则要求所有内容,并在 requirejs 完成后手动引导 angular(从 index.html 中删除 ng-app=""),并执行 `angular.bootstrap()´。因此,问题很可能是 angular 启动太早。


这确实是一个时间问题。我真的想要 requireJS 提供的 AMD 模块。我认为 head.js 不会对我有太大帮助。我已经让 Angular 和 Require 一起工作了,只是在这个控制器上与 OpenLayers 依赖项不起作用。 - Martijn
2
这就是回答的关键。你必须决定哪个框架给出了正确的语调。如果选择 requireJS,则手动加载所有需要的内容并引导 Angular(从 index.html 中删除 ng-app=""),并在 requirejs 完成后执行 angular.bootstrap()。因此,问题很可能是 Angular 启动得太早了。 - angabriel
好的观点。我已经有一个domReady函数(http://requirejs.org/docs/api.html#pageload),它在Angular引导之前等待dom加载,所以我没有使用ng-app。然而,可能dom已经准备好了,但是require还没有完成加载所有内容。我该如何检查require是否已经完成加载? - Martijn
如果我从requirejs回调函数中调用domReady函数会怎样?(http://requirejs.org/docs/api.html#config-callback) - Martijn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接