2013-04-17 65 views
17

我是AngularJS新手,我刚刚开始了解factory,servicecontroller的概念和差异。据我所知,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中是否有其他机制可以用来代替?

+0

我认为在提供函数中声明自定义工厂对象的重点在于它从应用程序的其余部分中抽象出来。 – Bart

+0

如果你确实需要一个构造函数,那么你在做什么很好! – ganaraj

+0

@ganaraj我“需要”它的原因是它可能会在控制器的生命周期中在控制器中多次重新初始化。我可以只返回一个常规对象,然后在其上有一个'init'方法,但我不明白那会更好。感谢您的反馈。 – NilsH

回答

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)中配置该单个服务实例。

+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

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

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

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"))) 

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