AngularJS中的服务、提供商和工厂之间有什么区别?


当前回答

句法糖是区别。只需要提供程序。或者换句话说,只有提供者才是真正的角度,所有其他提供者都是派生的(以减少代码)。还有一个简单的版本,叫做Value(),它只返回值,不返回计算或函数。偶数值是从提供程序派生的!

那么,为什么会出现这样的并发症,为什么我们不能只使用提供者而忘记其他一切呢?它应该可以帮助我们轻松编写代码,更好地进行沟通。开玩笑的回答是,它越复杂,框架的销售就越好。


可以返回value=value的提供程序一个可以实例化并返回=工厂(+值)提供程序可以实例化+做某事=服务(+工厂,+值)提供者=必须包含名为$get(+Factory,+Service,+Value)的属性

角注入为我们得出这一结论提供了第一个线索。

$injector用于检索提供者“不是服务,不是工厂,而是提供者”定义的对象实例。

更好的答案是:Angular服务由服务工厂创建。这些服务工厂是由服务提供程序创建的函数。服务提供程序是构造函数。实例化时,它们必须包含名为$get的属性,该属性保存服务工厂函数

因此,主供应器和注入器都将就位:)。当$get可以通过从IServiceProvider继承而在提供程序中实现时,Typescript就变得有趣了。

其他回答

对我来说,当我意识到它们都以相同的方式工作时,我就发现了这一点:通过运行一次某个东西,存储它们获得的值,然后在通过依赖注入引用时提取相同的存储值。

假设我们有:

app.factory('a', fn);
app.service('b', fn);
app.provider('c', fn);

三者之间的区别在于:

a的存储值来自运行fn。b的存储值来自newing fn。c的存储值来自首先通过newing fn获取一个实例,然后运行该实例的$get方法。

这意味着在AngularJS中有一个类似于缓存对象的东西,每次注入的值仅在第一次注入时分配一次,其中:

cache.a = fn()
cache.b = new fn()
cache.c = (new fn()).$get()

这就是为什么我们在服务中使用这个,并定义一个This$获取提供者。

正如这里的几个人正确指出的,工厂、供应商、服务,甚至价值和常量都是同一事物的版本。您可以将更通用的提供程序分解为所有这些提供程序。像这样:

这是本文的图片来源:

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

为了澄清这一点,从AngularJS源代码中,您可以看到一个服务只是调用工厂函数,而工厂函数反过来调用提供程序函数:

function factory(name, factoryFn) { 
    return provider(name, { $get: factoryFn }); 
}

function service(name, constructor) {
    return factory(name, ['$injector', function($injector) {
      return $injector.instantiate(constructor);
    }]);
}

工厂

如果给AngularJS一个函数,AngularJS将在请求工厂时缓存并注入返回值。

例子:

app.factory('factory', function() {
    var name = '';
    // Return value **is** the object that will be injected
    return {
        name: name;
    }
})

用法:

app.controller('ctrl', function($scope, factory) {
     $scope.name = factory.name;
});

服务

如果给AngularJS一个函数,AngularJS将调用new来实例化它。AngularJS创建的实例将在请求服务时缓存并注入。由于new用于实例化服务,因此关键字this是有效的,并引用实例。

例子:

app.service('service', function() {
     var name = '';
     this.setName = function(newName) {
         name = newName;
     }
     this.getName = function() {
         return name;
     }
});

用法:

app.controller('ctrl', function($scope, service) {
   $scope.name = service.getName();
});

供应商

给AngularJS一个函数,AngularJS将调用它的$get函数。它是$get函数的返回值,将在请求服务时缓存并注入。

提供程序允许您在AngularJS调用$get方法获取可注入对象之前配置提供程序。

例子:

app.provider('provider', function() {
     var name = '';
     this.setName = function(newName) {
          name = newName;
     }
     this.$get = function() {
         return {
            name: name
         }
     }
})

用法(作为控制器中的注射剂)

app.controller('ctrl', function($scope, provider) {
    $scope.name = provider.name;
});

用法(在调用$get以创建可注射对象之前配置提供程序)

app.config(function(providerProvider) {
    providerProvider.setName('John');
});

JS Fiddle演示

工厂/服务/供应商的“Hello world”示例:

var myApp=角度模块('myApp',[]);//服务风格,可能是最简单的myApp.service('helloWorldFromService',函数(){this.sayHello=函数(){return“你好,世界!”;};});//工厂风格,更加复杂myApp.factory('helloWorldFromFactory',函数(){返回{sayHello:函数(){return“你好,世界!”;}};});//提供程序风格、全面、可配置版本myApp.provider('helloWorld',函数(){this.name='默认值';这一点$get=函数(){var名称=this.name;返回{sayHello:函数(){return“您好,”+name+“!”;}}};this.setName=函数(名称){this.name=名称;};});//嘿,我们可以配置提供者!myApp.config(函数(helloWorldProvider){helloWorldProvider.setName('World');});函数MyCtrl($scope、helloWorld、helloWorldFromFactory、helloWorldFromService){$scope.hellos=[helloWorld.sayHello(),helloWorldFromFactory.sayHello(),helloWorldFromService.sayHello()];}<script src=“https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js“></script><body ng app=“myApp”><div ng controller=“MyCtrl”>{{hellos}}</div></body>