我已经看到angular.factory()和angular.service()被用来声明服务;然而,我找不到角。在官方文件的任何地方提供服务。

这两种方法有什么区别? 哪个应该用来做什么(假设它们做不同的事情)?


当前回答

简单地说…

Const user = { 名字:“约翰” }; / /工厂 const addLastNameFactory = (user, lastName) => ({ 用户, 姓, }); console.log (addLastNameFactory(用户、“母鹿”)); / /服务 const addLastNameService = (user, lastName) => { 用户。lastName = lastName;/ /坏!突变 返回用户; }; console.log (addLastNameService(用户、“母鹿”));

其他回答

  angular.service('myService', myServiceFunction);
  angular.factory('myFactory', myFactoryFunction);

我很难理解这个概念,直到我这样对自己说:

Service:你所写的函数将被new-ed:

  myInjectedService  <----  new myServiceFunction()

Factory:你写的函数(构造函数)将被调用:

  myInjectedFactory  <---  myFactoryFunction()

你怎么做取决于你自己,但有一些有用的模式……

比如写一个服务函数来公开一个公共API:

function myServiceFunction() {
  this.awesomeApi = function(optional) {
    // calculate some stuff
    return awesomeListOfValues;
  }
}
---------------------------------------------------------------------------------
// Injected in your controller
$scope.awesome = myInjectedService.awesomeApi();

或者使用工厂函数公开一个公共API:

function myFactoryFunction() {
  var aPrivateVariable = "yay";

  function hello() {
    return "hello mars " + aPrivateVariable;
  }
  
  // expose a public API
  return {
    hello: hello
  };
}
---------------------------------------------------------------------------------
// Injected in your controller
$scope.hello = myInjectedFactory.hello();

或者使用工厂函数返回构造函数:

function myFactoryFunction() {
    return function() {
        var a = 2;
        this.a2 = function() {
            return a*2;
        };
    };
}
---------------------------------------------------------------------------------
// Injected in your controller
var myShinyNewObject = new myInjectedFactory();
$scope.four = myShinyNewObject.a2();

用哪一个?

两者都可以达到同样的效果。然而,在某些情况下,工厂可以更灵活地使用更简单的语法创建可注入对象。这是因为myInjectedService必须始终是一个对象,而myInjectedFactory可以是一个对象、一个函数引用或任何值。例如,如果你写了一个服务来创建一个构造函数(就像上面的最后一个例子一样),它必须像这样被实例化:

var myShinyNewObject = new myInjectedService.myFunction()

这可能比这个更不可取:

var myShinyNewObject = new myInjectedFactory();

(但是首先应该警惕使用这种类型的模式,因为在控制器中新建对象会创建难以跟踪的依赖关系,这很难模拟测试。让一个服务为你管理对象集合比随意使用new()更好。


还有一件事,他们都是单身……

还要记住,在这两种情况下,angular都是在帮助你管理单例对象。无论注入服务或函数的位置或次数如何,都将获得对相同对象或函数的相同引用。(当工厂只是返回一个像数字或字符串的值时除外。在这种情况下,你将总是得到相同的值,但不是引用。)

这里所有的答案似乎都围绕着服务和工厂,这是有效的,因为这就是被问到的问题。但同样重要的是要记住,还有其他几个变量,包括provider()、value()和constant()。

关键是要记住,每一个都是另一个的特殊情况。每一种特殊情况都允许你用更少的代码做同样的事情。每一种都有一些额外的限制。

要决定什么时候使用哪个,你只需看看哪个允许你用更少的代码做你想做的事情。下面这张图说明了它们是多么相似:

对于一个完整的分步分解和快速参考何时使用每一个,你可以访问我得到这张图片的博客文章:

http://www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory-in-angularjs/

简单地说…

Const user = { 名字:“约翰” }; / /工厂 const addLastNameFactory = (user, lastName) => ({ 用户, 姓, }); console.log (addLastNameFactory(用户、“母鹿”)); / /服务 const addLastNameService = (user, lastName) => { 用户。lastName = lastName;/ /坏!突变 返回用户; }; console.log (addLastNameService(用户、“母鹿”));

线索就在名字里

服务和工厂彼此相似。两者都将产生一个可以注入到其他对象中的单例对象,因此通常可以互换使用。

它们旨在从语义上用于实现不同的设计模式。

服务用于实现服务模式

服务模式是将应用程序分解为逻辑一致的功能单元的模式。例如API访问器或一组业务逻辑。

这在Angular中尤其重要,因为Angular模型通常只是从服务器上提取的JSON对象,所以我们需要一个地方来放置我们的业务逻辑。

这是一个Github服务的例子。它知道如何与Github对话。它知道url和方法。我们可以把它注入到控制器中,它会生成并返回一个承诺。

(function() {
  var base = "https://api.github.com";

  angular.module('github', [])
    .service('githubService', function( $http ) {
      this.getEvents: function() {
        var url = [
          base,
          '/events',
          '?callback=JSON_CALLBACK'
        ].join('');
        return $http.jsonp(url);
      }
    });
  )();

工厂实现工厂模式

另一方面,工厂旨在实现工厂模式。一种工厂模式,其中我们使用工厂函数来生成对象。通常我们会用它来建立模型。下面是一个返回Author构造函数的工厂:

angular.module('user', [])
  .factory('User', function($resource) {
    var url = 'http://simple-api.herokuapp.com/api/v1/authors/:id'
    return $resource(url);
  })

我们可以这样使用它:

angular.module('app', ['user'])
  .controller('authorController', function($scope, User) {
    $scope.user = new User();
  })

注意,工厂也返回单例对象。

工厂可以返回构造函数

因为工厂只是返回一个对象,所以它可以返回任何类型的对象,包括构造函数,如上所述。

工厂返回一个对象;服务是可更新的

另一个技术差异在于服务和工厂的组合方式。一个新的服务函数将生成对象。工厂函数将被调用并返回该对象。

服务是可更新的构造函数。 工厂被简单地调用并返回一个对象。

这意味着在服务中,我们将“This”附加到构造函数的上下文中,它将指向正在构造的对象。

为了说明这一点,下面是使用服务和工厂创建的相同的简单对象:

angular.module('app', [])
  .service('helloService', function() {
    this.sayHello = function() {
      return "Hello!";
    }
  })
  .factory('helloFactory', function() {
    return {
      sayHello: function() {
        return "Hello!";
      }
    }
  });

工厂模式更灵活,因为它可以返回函数和值以及对象。

恕我直言,在服务模式中没有太多意义,因为它所做的一切都可以通过工厂轻松完成。例外可能是:

如果您出于某种原因关心实例化服务的声明类型——如果您使用服务模式,则构造函数将是新服务的类型。 如果您已经有一个正在其他地方使用的构造函数,并且还想将其用作服务(尽管如果您想向其中注入任何东西,可能没有多大用处!)。

Arguably, the service pattern is a slightly nicer way to create a new object from a syntax point of view, but it's also more costly to instantiate. Others have indicated that angular uses "new" to create the service, but this isn't quite true - it isn't able to do that because every service constructor has a different number of parameters. What angular actually does is use the factory pattern internally to wrap your constructor function. Then it does some clever jiggery pokery to simulate javascript's "new" operator, invoking your constructor with a variable number of injectable arguments - but you can leave out this step if you just use the factory pattern directly, thus very slightly increasing the efficiency of your code.