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

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


当前回答

我花了一些时间试图弄清楚其中的区别。

我认为工厂函数使用模块模式,服务函数使用标准的java脚本构造函数模式。

其他回答

以下是主要的区别:

服务

语法:模块。service('serviceName',函数);

结果:当将serviceName声明为可注入参数时,你将得到传递给module.service的函数实例。

使用方法:可以通过简单地将()附加到注入的函数引用来共享有用的实用程序函数。也可以用injectedArg运行。调用(这个)或类似的方法。

工厂

语法:模块。factory('factoryName',函数);

结果:当将factoryName声明为一个可注入参数时,将为您提供通过调用传递给module.factory的函数引用返回的值。

用法:可能用于返回一个'class'函数,然后可以重新创建实例。

下面是使用服务和工厂的示例。阅读更多关于AngularJS服务vs工厂的文章。

你也可以查看AngularJS的文档和类似的关于stackoverflow混淆服务和工厂的问题。

简单地说…

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!";
      }
    }
  });

我花了一些时间试图弄清楚其中的区别。

我认为工厂函数使用模块模式,服务函数使用标准的java脚本构造函数模式。

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