根据我的理解,当我在工厂中返回一个被注入到控制器的对象。当在服务中,我使用这个处理对象,不返回任何东西。

我假设服务总是单例的,并且每个控制器中都会注入一个新的工厂对象。然而,正如事实证明的那样,工厂对象也是单例的吗?

演示的示例代码:

var factories = angular.module('app.factories', []);
var app = angular.module('app',  ['ngResource', 'app.factories']);

factories.factory('User', function () {
  return {
    first: 'John',
    last: 'Doe'
  };
});

app.controller('ACtrl', function($scope, User) {
  $scope.user = User;
});

app.controller('BCtrl', function($scope, User) {
  $scope.user = User;
});

更改用户时。首先在ACtrl中,结果是那个用户。BCtrl中的first也改变了,例如User is a singleton?

我的假设是一个新的实例被注入到一个带有工厂的控制器中?


当前回答

服务样式:(可能是最简单的一种)返回实际函数:用于共享实用程序函数,只需将()附加到注入的函数引用即可调用。

AngularJS中的服务是一个单例JavaScript对象,它包含一组函数

var myModule = angular.module("myModule", []);

myModule.value  ("myValue"  , "12345");

function MyService(myValue) {
    this.doIt = function() {
        console.log("done: " + myValue;
    }
}

myModule.service("myService", MyService);
myModule.controller("MyController", function($scope, myService) {

    myService.doIt();

});

工厂样式(更复杂但更复杂)返回函数的返回值:在java中实例化一个对象,如new object()。

工厂是一个创造价值的函数。当服务、控制器等需要从工厂注入价值时,工厂会按需创造价值。一旦创建,该值将被所有需要注入的服务、控制器等重用。

var myModule = angular.module("myModule", []);

myModule.value("numberValue", 999);

myModule.factory("myFactory", function(numberValue) {
    return "a value: " + numberValue;
})  
myModule.controller("MyController", function($scope, myFactory) {

    console.log(myFactory);

});

提供者样式:(完整的、可配置的版本)返回函数的$get函数的输出:可配置。

AngularJS中的Providers是你能创建的最灵活的工厂形式。向模块注册提供者就像向服务或工厂注册一样,只是使用了provider()函数。

var myModule = angular.module("myModule", []);

myModule.provider("mySecondService", function() {
    var provider = {};
    var config   = { configParam : "default" };

    provider.doConfig = function(configParam) {
        config.configParam = configParam;
    }

    provider.$get = function() {
        var service = {};

        service.doService = function() {
            console.log("mySecondService: " + config.configParam);
        }

        return service;
    }

    return provider;
});

myModule.config( function( mySecondServiceProvider ) {
    mySecondServiceProvider.doConfig("new config param");
});

myModule.controller("MyController", function($scope, mySecondService) {

    $scope.whenButtonClicked = function() {
        mySecondService.doIt();
    }

});

斯库尔克·延科夫

<!DOCTYPE html> <html ng-app="app"> <head> <script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.min.js"></script> <meta charset=utf-8 /> <title>JS Bin</title> </head> <body ng-controller="MyCtrl"> {{serviceOutput}} <br/><br/> {{factoryOutput}} <br/><br/> {{providerOutput}} <script> var app = angular.module( 'app', [] ); var MyFunc = function() { this.name = "default name"; this.$get = function() { this.name = "new name" return "Hello from MyFunc.$get(). this.name = " + this.name; }; return "Hello from MyFunc(). this.name = " + this.name; }; // returns the actual function app.service( 'myService', MyFunc ); // returns the function's return value app.factory( 'myFactory', MyFunc ); // returns the output of the function's $get function app.provider( 'myProv', MyFunc ); function MyCtrl( $scope, myService, myFactory, myProv ) { $scope.serviceOutput = "myService = " + myService; $scope.factoryOutput = "myFactory = " + myFactory; $scope.providerOutput = "myProvider = " + myProv; } </script> </body> </html>

jsbin

<!DOCTYPE html> <html ng-app="myApp"> <head> <script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.min.js"></script> <meta charset=utf-8 /> <title>JS Bin</title> </head> <body> <div ng-controller="MyCtrl"> {{hellos}} </div> <script> var myApp = angular.module('myApp', []); //service style, probably the simplest one myApp.service('helloWorldFromService', function() { this.sayHello = function() { return "Hello, World!" }; }); //factory style, more involved but more sophisticated myApp.factory('helloWorldFromFactory', function() { return { sayHello: function() { return "Hello, World!" } }; }); //provider style, full blown, configurable version myApp.provider('helloWorld', function() { this.name = 'Default'; this.$get = function() { var name = this.name; return { sayHello: function() { return "Hello, " + name + "!" } } }; this.setName = function(name) { this.name = name; }; }); //hey, we can configure a provider! myApp.config(function(helloWorldProvider){ helloWorldProvider.setName('World'); }); function MyCtrl($scope, helloWorld, helloWorldFromFactory, helloWorldFromService) { $scope.hellos = [ helloWorld.sayHello(), helloWorldFromFactory.sayHello(), helloWorldFromService.sayHello()]; } </script> </body> </html>

斯菲德尔

其他回答

以下是主要的区别:

服务

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

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

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

工厂

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

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

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

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

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

生活的例子

" Hello world "的例子

与工厂/服务/供应商:

var myApp = angular.module('myApp', []);
 
//service style, probably the simplest one
myApp.service('helloWorldFromService', function() {
    this.sayHello = function() {
        return "Hello, World!"
    };
});
 
//factory style, more involved but more sophisticated
myApp.factory('helloWorldFromFactory', function() {
    return {
        sayHello: function() {
            return "Hello, World!"
        }
    };
});
    
//provider style, full blown, configurable version     
myApp.provider('helloWorld', function() {
    // In the provider function, you cannot inject any
    // service or factory. This can only be done at the
    // "$get" method.
 
    this.name = 'Default';
 
    this.$get = function() {
        var name = this.name;
        return {
            sayHello: function() {
                return "Hello, " + name + "!"
            }
        }
    };
 
    this.setName = function(name) {
        this.name = name;
    };
});
 
//hey, we can configure a provider!            
myApp.config(function(helloWorldProvider){
    helloWorldProvider.setName('World');
});
        
 
function MyCtrl($scope, helloWorld, helloWorldFromFactory, helloWorldFromService) {
    
    $scope.hellos = [
        helloWorld.sayHello(),
        helloWorldFromFactory.sayHello(),
        helloWorldFromService.sayHello()];
}​

服务样式:(可能是最简单的一种)返回实际函数:用于共享实用程序函数,只需将()附加到注入的函数引用即可调用。

AngularJS中的服务是一个单例JavaScript对象,它包含一组函数

var myModule = angular.module("myModule", []);

myModule.value  ("myValue"  , "12345");

function MyService(myValue) {
    this.doIt = function() {
        console.log("done: " + myValue;
    }
}

myModule.service("myService", MyService);
myModule.controller("MyController", function($scope, myService) {

    myService.doIt();

});

工厂样式(更复杂但更复杂)返回函数的返回值:在java中实例化一个对象,如new object()。

工厂是一个创造价值的函数。当服务、控制器等需要从工厂注入价值时,工厂会按需创造价值。一旦创建,该值将被所有需要注入的服务、控制器等重用。

var myModule = angular.module("myModule", []);

myModule.value("numberValue", 999);

myModule.factory("myFactory", function(numberValue) {
    return "a value: " + numberValue;
})  
myModule.controller("MyController", function($scope, myFactory) {

    console.log(myFactory);

});

提供者样式:(完整的、可配置的版本)返回函数的$get函数的输出:可配置。

AngularJS中的Providers是你能创建的最灵活的工厂形式。向模块注册提供者就像向服务或工厂注册一样,只是使用了provider()函数。

var myModule = angular.module("myModule", []);

myModule.provider("mySecondService", function() {
    var provider = {};
    var config   = { configParam : "default" };

    provider.doConfig = function(configParam) {
        config.configParam = configParam;
    }

    provider.$get = function() {
        var service = {};

        service.doService = function() {
            console.log("mySecondService: " + config.configParam);
        }

        return service;
    }

    return provider;
});

myModule.config( function( mySecondServiceProvider ) {
    mySecondServiceProvider.doConfig("new config param");
});

myModule.controller("MyController", function($scope, mySecondService) {

    $scope.whenButtonClicked = function() {
        mySecondService.doIt();
    }

});

斯库尔克·延科夫

<!DOCTYPE html> <html ng-app="app"> <head> <script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.min.js"></script> <meta charset=utf-8 /> <title>JS Bin</title> </head> <body ng-controller="MyCtrl"> {{serviceOutput}} <br/><br/> {{factoryOutput}} <br/><br/> {{providerOutput}} <script> var app = angular.module( 'app', [] ); var MyFunc = function() { this.name = "default name"; this.$get = function() { this.name = "new name" return "Hello from MyFunc.$get(). this.name = " + this.name; }; return "Hello from MyFunc(). this.name = " + this.name; }; // returns the actual function app.service( 'myService', MyFunc ); // returns the function's return value app.factory( 'myFactory', MyFunc ); // returns the output of the function's $get function app.provider( 'myProv', MyFunc ); function MyCtrl( $scope, myService, myFactory, myProv ) { $scope.serviceOutput = "myService = " + myService; $scope.factoryOutput = "myFactory = " + myFactory; $scope.providerOutput = "myProvider = " + myProv; } </script> </body> </html>

jsbin

<!DOCTYPE html> <html ng-app="myApp"> <head> <script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.min.js"></script> <meta charset=utf-8 /> <title>JS Bin</title> </head> <body> <div ng-controller="MyCtrl"> {{hellos}} </div> <script> var myApp = angular.module('myApp', []); //service style, probably the simplest one myApp.service('helloWorldFromService', function() { this.sayHello = function() { return "Hello, World!" }; }); //factory style, more involved but more sophisticated myApp.factory('helloWorldFromFactory', function() { return { sayHello: function() { return "Hello, World!" } }; }); //provider style, full blown, configurable version myApp.provider('helloWorld', function() { this.name = 'Default'; this.$get = function() { var name = this.name; return { sayHello: function() { return "Hello, " + name + "!" } } }; this.setName = function(name) { this.name = name; }; }); //hey, we can configure a provider! myApp.config(function(helloWorldProvider){ helloWorldProvider.setName('World'); }); function MyCtrl($scope, helloWorld, helloWorldFromFactory, helloWorldFromService) { $scope.hellos = [ helloWorld.sayHello(), helloWorldFromFactory.sayHello(), helloWorldFromService.sayHello()]; } </script> </body> </html>

斯菲德尔

对我来说,当我意识到它们都以相同的方式工作时,我得到了启示:通过运行一次,存储它们得到的值,然后在通过依赖注入引用时吐出相同的存储值。

假设我们有:

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

这三者的区别在于:

A的存储值来自运行fn,换句话说:fn() B的存储值来自于new fn,换句话说:new fn() C的存储值来自于首先通过new fn获得一个实例,然后运行实例的$get方法

这意味着,在angular内部有一个类似缓存对象的东西,它的每次注入的值只被赋值一次,当它们第一次被注入时,并且在:

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

这就是为什么我们在服务中使用This,并定义一个This。$get在供应商。

You can understand the difference with this analogy - Consider the difference between a normal function that will return some value and constructor function that will get instantiated using new keyword.So creating factory is just similar to create normal function that will return some value(primitive or an object) whereas creating service is like creating constructor function(OO class) of which we can create instance using new keyword. The only thing to notice is here is that when we use Service method to create services it will automatically create instance of it using dependency injection mechanism supported by AngularJS