创建可注入类(构造函数)

时间:2013-04-17 06:01:01

标签: javascript angularjs

我是AngularJS新手,我刚刚开始理解factoryservicecontroller的概念和差异。据我所知,factory用于返回可以注入的“值对象”。我见过的大多数例子都是这样的:

angular.module('module.factories', function() {
    factory('FactoryObject', function() {
        return {
            someFunction: function(someParam) {};
            someOtherFunction: function(someOtherParam) {});
        };
    });
});

在我的controller中,我希望能够使用此对象,但我想在控制器中初始化/实例化它,因为它可以根据控制器中的事件/操作重新初始化。因此,我想知道我是否可以在工厂中返回构造函数?

angular.module('module.factories', function() {
    factory('FactoryObject', function() {

        function FactoryObject(initParam) {
        }

        FactoryObject.prototype.someFunction = function() {};

        return FactoryObject;

    });
});

这是角度工厂的合适模式吗?或者将工厂用于这样的自定义对象只是“过度杀伤”?我应该将它包含在库js文件中并从那里引用它吗?将它放入工厂的一个好处是可以很容易地在测试中模拟它,因为它将被注入到使用它的地方。 Angular中是否还有其他机制可以替代使用?

4 个答案:

答案 0 :(得分:8)

我遇到了同样的问题。这是我实施的内容:

angular.module('foo', [])
.factory('Foo', ['$http', function($http) {
  return function(a, b) {
    this.arr = [];
    this.a = a;
    this.b = b;
    this.random = Math.floor(Math.random()*11);

    this.someFunc = function(c) {
      this.arr.push(c);
    };
  };
}]);

现在,我可以这样做:

var f1 = new Foo('A', 'B');
f1.random;  // i.e. 0
f1.someFunc('z');  // only affects f1.arr
var f2 = new Foo('C', 'D');
f2.random;  // i.e. 8
f2.someFunc('y');  // only affects f2.arr

使事情更加模块化。希望有所帮助。

答案 1 :(得分:3)

你是对的,这是创建可注射"类"的方法。 (构造函数)。但是,只有当您需要注入要由您的类使用的其他内容时才需要使用factory

.factory('Class', ['$q', function ($q) {
    function Class () {}
    Class.prototype = {
        constructor: Class,
        doSomeAsyncAction: function () {
            return $q(function (resolve, reject) {
                // ...
            });
        },
        // ...
    };
    return Class;
})

如果您要创建一个完全独立的类(例如某些数据结构),则可以使用constant,这样即使在服务提供商中您的类也可用:

(function (undefined) {
    function Class () {}
    Class.prototype = { ... };
    angular.module(...)
        .constant('Class', Class);
})();

作为旁注,使用provider并不会对此有所帮助。提供者提供完全不同的目的,并且(除其他外)返回工厂函数,然后在第一次请求注入时使用_once_来创建服务的单个实例。提供程序用于让您在应用程序构造的_config阶段(see documentation)中配置该单个服务实例。

答案 2 :(得分:1)

我有同样的问题。我发现了一篇关于如何设置面向对象的AngularJS服务的精彩文章。 Here's the article。请注意有关使用工厂而非服务的说明。它还包括扩展您的对象。我发现它非常容易设置,它与Angular完美契合,同时保持Javascript简单直接。

对于作为单例并且不需要实例化的工厂服务,我使用具有一些性能优势的对象文字方法。

答案 3 :(得分:1)

以下是我解决问题的方法:

(function (myModule) {
    'use strict';

    myModule.service('myService', [
        function() {
            var serivce = this;
            var obj = null;

            service.func1 = function(a, b) {

            }

            service.func2 = function(c, d) {
                . . .
                return something;
            }

            var constructor = function(myObj) {
                obj = myObj;

                return service;
            }

            return constructor;
        }
    ]);
}(angular.module("myModule")))

(function(myModule) {
    'use strict';

    myModule.controller('myController', [
        '$scope', 'myService', function($scope, myService) {

            var service = myService($scope.someObj);

            $scope.someOtherObj = service.func2($scope.a, $scope.b);

        }
    ]);
}(angular.module("myModule")))

从服务返回的唯一内容是构造函数,然后服务返回服务的其余部分。