1

编辑:我设法让我的单元测试运行 - 我将包含服务的代码移动到不同的文件和不同的模块,使这个新模块成为 fooBar 模块的要求,然后在调用每个“it”块之前,引入代码beforeEach(module(<new_service_module_name))。但是,我的应用程序仍然无法运行。控制台也没有错误。这是唯一剩下的问题——当我使用全局范围来定义控制器时,应用程序可以工作,但是当我使用 angular.module.controller 时——它不会。

我有一个app.js包含以下内容的文件:

'use strict';

var app = angular.module('fooBar', []);

app.config(['$routeProvider', function($routeProvider) {
  $routeProvider.
  when('/', {
    templateUrl: 'partials/form-view.html',
    controller: FormViewCtrl
  }).
  when('/resultDisplay', {
    templateUrl: 'partials/table-view.html',
    controller: TableViewCtrl
  }).
  otherwise({redirectTo: '/'});
}]);

app.service('searchResults', function() {
  var results = {};

  return {
    getResults: function() {
      return results;
    },
    setResults: function(resultData) {
      results = resultData;
    }
  };
});

我有另一个文件controllers.js,其中包含以下内容:

'use strict';

var app = angular.module('fooBar', []);

app.controller('FormViewCtrl', ['$scope', '$location', '$http', 'searchResults', 
    function ($scope, $location, $http, searchResults) {
        //Controller code
}]);

searchResults是我创建的一个服务,它只有 getter 和 setter 方法。上面的控制器使用 setter 方法,因此服务被注入其中。

结果,我的应用程序无法运行!如果我将控制器代码更改为全局的,如下所示:

function ($scope, $location, $http, searchResults) {
    //Controller code
}

然后应用程序工作!

此外,如果我使用全局范围,则以下单元测试用例有效:

'use strict';

/*jasmine specs for controllers go here*/
describe('Foo Bar', function() {

    describe('FormViewCtrl', function() {
        var scope, ctrl;

        beforeEach(module('fooBar'));

        beforeEach(inject(function($rootScope, $controller) {
            scope = $rootScope.$new();
            ctrl = $controller('FormViewCtrl', {$scope: scope});
        }));
        }
        //"it" blocks
}

如果我恢复到模块范围,我会收到错误 -
Error: Unknown provider: searchResultsProvider <- searchResults

因此,通过使用全局范围,我的应用程序和单元测试运行,但通过使用 app.controller,它们似乎中断了。

我注意到的另一点是,如果我将控制器代码包含在app.js而不是 中controllers.js,那么应用程序和单元测试将再次开始工作。但是我不能将它们包含在同一个文件中 - 如何在不破坏应用程序和单元测试的情况下让它在角度范围内运行?

4

4 回答 4

9

你不需要走那条路。您可以使用模块化方法,但问题在于您的第二个参数。

在你的 app.js 你有这个:

var app = angular.module('fooBar', []);

然后在你的控制器中,你有这个:

var app = angular.module('fooBar', []);

你在那里做的是两次定义模块。如果您只是尝试附加到应用程序模块,则不能传入第二个参数(空数组:)[],因为这会创建一个全新的模块,覆盖第一个。

以下是我的做法(基于这篇关于构建大型 AngularJS 应用程序的文章。

应用程序.js:

angular.module('fooBar',['fooBar.controllers', 'fooBar.services']);
angular.module('fooBar.controllers',[]);
angular.module('fooBar.services', []);
...etc

控制器.js

angular.module('foobar.controllers') // notice the lack of second parameter
    .controller('FormViewCtrl', function($scope) {
        //controller stuffs
    });

或者,对于非常大的项目,建议不要按类型(指令、过滤器、服务、控制器)对顶级模块进行分组,而是按功能(包括所有部分......这样做的原因是完全模块化- 您可以创建一个具有相同名称、新部分和代码的新模块,将其放入您的项目中作为替换,它会简单地工作),例如

应用程序.js

angular.module('fooBar',['fooBar.formView', 'fooBar.otherView']);
angular.module('fooBar.formView',[]);
angular.module('fooBar.otherView', []);
...etc

然后在一个formView挂在网络根目录下的文件夹中,然后根据类型将文件分开,例如:

formView.directives
formView.controllers
formView.services
formView.filters

And then, in each of those files, you open with: 

angular.module('formView')
    .controller('formViewCtrl', function($scope) {

angular.module('formView')
    .factory('Service', function() {

etc etc

高温高压

于 2013-05-18T16:28:09.503 回答
2

好的 - 我终于想通了。基本上,如果您希望使用模块范围而不是全局范围,那么我们需要执行以下操作(如果您有类似app.jsand的设置controllers.js):

  1. 在 app.js 中,定义模块范围:

    var myApp = angular.module(<module_name>, [<dependencies>]);

  2. 在 controllers.js 中,不要再次定义 myApp - 相反,直接使用它,如:

    myApp.controller(..);

成功了——我的应用程序和单元测试现在可以正常工作了!

于 2013-04-14T09:00:16.467 回答
1

最佳实践是只有一个全局变量,即您的应用程序并将所有需要的模块功能附加到该变量,以便您的应用程序启动

var app = angular.module('app',[ /* Dependencies */ ]);

在您的 controller.js 中,您再次将其启动到一个新变量中,丢失了您之前附加到它的所有服务和配置,只启动您的应用程序变量一次,再次执行会使您失去附加到它的服务

然后添加一个服务(工厂版)

app.factory('NewLogic',[ /* Dependencies */ , function(  /* Dependencies */ ) {
return {
function1: function(){
   /* function1 code */

    }
  }
}]);

对于控制器

app.controller('NewController',[ '$scope' /* Dependencies */ , function( $scope /* Dependencies */ ) {
$scope.function1 = function(){
   /* function1 code */
    };
  }
}]);

对于指令和配置也类似,您创建一个应用程序模块并将所有需要的控制器、指令和服务附加到它,但都包含在父应用程序模块变量中。

我一次又一次地读到,对于 javascript,最好的做法是只有一个全局变量,所以 angularjs 架构确实很好地满足了这一要求,

哦,实际上并不需要依赖项的数组包装器,但如果你想缩小你的 JS,那么它会创建一堆全局变量并完全破坏应用程序,这是一个好主意,始终坚持最佳实践,而不是做变通来让事情正常工作

于 2013-06-24T15:04:35.630 回答
0

就我而言,我定义了一个新的提供者,比如说,xyz

angular.module('test')
.provider('xyz', function () {
    ....
});

当您要配置上述提供者时,您已经将其注入并附加了“提供者”字符串。

前任:

angular.module('App', ['test'])
.config(function (xyzProvider) {
     // do something with xyzProvider....
});

如果您在没有 'Provider' 字符串的情况下注入上述提供程序,您将在 OP 中得到类似的错误。

于 2013-10-03T13:15:08.640 回答