RequireJs依赖项的角度执行顺序

时间:2015-08-21 22:36:15

标签: angularjs requirejs

我最近将我的项目从bootstrapping angular通过ng-app默认方法转换为使用RequireJs并手动执行。一切都在大部分时间都能很好地工作,但是有一部分时间我得到错误,说我的控制器和登录页面的服务是未定义的,所以控制器没有正确加载,值也没有约束。

我认为问题源于依赖关系的执行顺序。首先,这是错误:

错误:[ng:areq] http://errors.angularjs.org/1.3.15/ng/areq?p0=NavController&p1=not%20aNaNunction%2C%20got%20undefined

错误:[$ injector:unpr] http://errors.angularjs.org/1.3.15/ $ injector / unpr?p0 = UsersServiceProvider%20%3C-%20UsersService%20%3C-%20LoginController

到目前为止,我只在Chrome中看到了这个问题,当我打开javascript控制台时,一切似乎都有效。我插入了一些console.log()语句,以便了解这些脚本中活动的顺序。对于三个文件,routeConfig.js,nav.js和usersService.js我在define函数的第一行有一个console.log,另一个在角度定义函数的第一行:

routeConfig.js:

define(['angularAMD',
        'angular-route',
        'uiBootstrap',
        'lib/angularSlideables',
        'lib/ng-infinite-scroll',
        'lib/angular-modal-service'], function (angularAMD) {

    console.log('top of routeConfig');

    var app = angular.module('svlPlatform', ['ngRoute', 'ui.bootstrap', 'angularSlideables', 'infinite-scroll', 'angularModalService']).value('THROTTLE_MILLISECONDS', 750);

    app.config(['$routeProvider', function ($routeProvider, $httpProvider) {

        console.log('inside routeConfig');

        //  Because angularAMD is built on requireJS, the following paths to controllerUrl follow requireJs's conventions.
        //  They don't need a .js extention and they are relative to the baseUrl specified in require.config.
        $routeProvider
            .when('/login', angularAMD.route({
                templateUrl: 'views/login.html',
                controllerUrl: 'controllers/login'
            }))
            .when('/me', angularAMD.route({
                templateUrl: 'views/me.html',
                controllerUrl: 'controllers/me'
            }))   //this continues and returns app...

nav.js:

define(['config/routeConfig', 'services/authService', 'services/usersService', 'services/menuService'], function(app) {

    console.log('top of nav controller');

    app.controller('NavController', ['$log', '$anchorScroll', '$location', '$rootScope', 'AuthService', 'UsersService', 'MenuService',
        function ($log, $anchorScroll, $location, $rootScope, auth, users, menu) {

        console.log('inside nav controller');

            var vm = this;
            menuScope = this;

            function loadMenu() {
                menu.items().then(function(response){
                    vm.menuItems = response.data.menuItems;
                    $('body').css("background-color","#f2f2f2");
                    markMenuActive(vm.menuItems);
                }, function(error) {
                    console.log('There was a problem getting the menu data.');
                });
            }   //continues...

usersService.js

define(['config/routeConfig', 'utils/urlBuilder', 'services/menuService'], function (app, _urlBuilder) {

    console.log('top of users service');

    var urlBuilder = _urlBuilder;
    app.factory('UsersService', ['$http', 'MenuService', function ($http, menu) {

        console.log('inside users service');

        var meCache;
        var refreshMeCache = function () {
            meCache = $http.get('/api/v1/users/me');
            menu.refreshItemsCache();
        };   //continues...

这是我的requireJs配置:

require.config({
    baseUrl: 'javascripts',
    paths: {
        'angular': '//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min',
        'angular-route': '//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-route.min',
        'bootstrapJs': '//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min',
        'uiBootstrap': '//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.12.1/ui-bootstrap-tpls.min',
        'angularAMD': '//cdn.jsdelivr.net/angular.amd/0.2.0/angularAMD.min'
    },
    shim: {
        'angularAMD': ['angular'],
        'bootstrapJs': [],
        'uiBootstrap': ['angular'],
        'lib/angularSlideables': ['angular'],
        'lib/ng-infinite-scroll': ['angular'],
        'angular-route': ['angular'],
        'lib/angular-modal-service': ['angular']
    },
    deps: [
        'bootstrapJs',
        'config/routeConfig',
        'services/authService',
        'services/usersService',
        'services/menuService',
        'controllers/nav',
        'controllers/main',
        'lib/angular-modal-service',
        'config/config',
        'app'
    ]
});

当正确加载登录页面(应用程序加载的第一页)时,我打开控制台后会看到这个:

top of routeConfig
top of users service
top of nav controller
inside routeConfig
inside users service
inside nav controller

但是当页面没有正确加载时,这就是我在控制台中看到的内容。

top of routeConfig
inside routeConfig
top of users service
top of nav controller

...然后错误

我不了解自举过程或要求新闻。加载过程足以弄清楚为什么会发生这种情况以及如何解决它。感谢有任何想法的人。感谢。

1 个答案:

答案 0 :(得分:1)

也许这是解决这个问题的最佳方法,也许不是。我放弃了尝试使用require在require config中指定任何类型的加载顺序或使用任何模块定义。我强迫它让我的几个控制器和服务模块返回应用程序,让它们依赖于系列而不是并行,这种力量需要按照我指定的顺序运行脚本。

所以,不是让nav.js和usersService.js依赖于routeConfig.js,它为这两个组件提供了app对象,我的服务依赖于routeConfig.js,而nav.js模块依赖于usersService(现在返回其app对象)。此方法可以继续包括需要在引导之前加载的其他控制器和服务。然后我最后调用另一个文件app.js,它调用angular.bootstrap()(在我的情况下为angularAMD.bootstrap()),现在一切正常。