when - AngularJS: Serviço vs provedor vs fábrica




when does angularjs create an instance of a service (20)

JS Fiddle Demo

Exemplo de "Olá mundo" com factory / service / provider :

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

Quais são as diferenças entre um Service , Provider e Factory no AngularJS?


Fábrica

Você dá uma função ao AngularJS, o AngularJS armazenará em cache e injetará o valor de retorno quando a fábrica for solicitada.

Exemplo:

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

Uso:

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

Serviço

Você dá uma função ao AngularJS, o AngularJS irá chamar new para instanciá-lo. É a instância que o AngularJS cria que será armazenado em cache e injetado quando o serviço for solicitado. Como o novo foi usado para instanciar o serviço, a palavra - chave é válida e refere-se à instância.

Exemplo:

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

Uso:

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

Fornecedor

Você dá uma função ao AngularJS e o AngularJS chamará sua $getfunção. É o valor de retorno da $getfunção que será armazenada em cache e injetada quando o serviço é solicitado.

Os provedores permitem que você configure o provedor antes que o AngularJS chame o $getmétodo para obter o injetável.

Exemplo:

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

Uso (como injetável em um controlador)

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

Uso (configurar o provedor antes $geté chamado para criar o injetável)

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

Todos os serviços são singletons ; eles são instanciados uma vez por aplicativo. Eles podem ser de qualquer tipo , seja um primitivo, um literal de objeto, uma função ou até mesmo uma instância de um tipo personalizado.

Os métodos value , factory , service , constant e provider são todos provedores. Eles ensinam o injetor como instanciar os serviços.

O mais detalhado, mas também o mais abrangente, é uma receita de provedor. Os quatro tipos de receita restantes - Valor, Fábrica, Serviço e Constante - são apenas açúcar sintático sobre uma receita de provedor .

  • A receita de valor é o caso mais simples, em que você instancia o serviço por conta própria e fornece o valor instanciado ao injetor.
  • A receita Factory fornece ao Injector uma função de fábrica que ele chama quando precisa instanciar o serviço. Quando chamado, a função de fábrica cria e retorna a instância de serviço. As dependências do Serviço são injetadas como argumentos das funções. Então, usando esta receita adiciona as seguintes habilidades:
    • Capacidade de usar outros serviços (tem dependências)
    • Inicialização do serviço
    • Inicialização atrasada / lenta
  • A receita de serviço é quase a mesma que a receita de fábrica, mas aqui o Injector chama um construtor com o novo operador em vez de uma função de fábrica.
  • A receita do provedor geralmente é um exagero . Ele adiciona mais uma camada de indireto, permitindo que você configure a criação da fábrica.

    Você deve usar a receita do Provedor somente quando desejar expor uma API para configuração de todo o aplicativo que deve ser feita antes de o aplicativo ser iniciado. Isso geralmente é interessante apenas para serviços reutilizáveis ​​cujo comportamento pode precisar variar um pouco entre os aplicativos.

  • A receita constante é como a receita de valor, exceto que ela permite definir serviços que estão disponíveis na fase de configuração . Mais cedo do que os serviços criados usando a receita do valor. Ao contrário dos valores, eles não podem ser decorados com decorator .
Veja a documentação do provedor .


Entendendo o AngularJS Factory, Service and Provider

Todos eles são usados ​​para compartilhar objetos singleton reutilizáveis. Ele ajuda a compartilhar códigos reutilizáveis ​​em seu aplicativo / vários componentes / módulos.

Do Service/Factory Docs:

  • Lazily instanciado - Angular instancia um serviço / fábrica apenas quando um componente de aplicativo depende dele.
  • Singletons - Cada componente dependente de um serviço obtém uma referência à instância única gerada pela fábrica de serviços.

Fábrica

Uma fábrica é uma função onde você pode manipular / adicionar lógica antes de criar um objeto, então o objeto recém-criado é retornado.

app.factory('MyFactory', function() {
    var serviceObj = {};
    //creating an object with methods/functions or variables
    serviceObj.myFunction = function() {
        //TO DO:
    };
    //return that object
    return serviceObj;
});

Uso

Pode ser apenas uma coleção de funções como uma classe. Portanto, ele pode ser instanciado em diferentes controladores quando você o injetar dentro de suas funções controlador / fábrica / diretiva. É instanciado apenas uma vez por aplicativo.

Serviço

Simplesmente enquanto olha para os serviços, pense no protótipo do array. Um serviço é uma função que instancia um novo objeto usando a palavra-chave 'new'. Você pode adicionar propriedades e funções a um objeto de serviço usando a thispalavra - chave. Ao contrário de uma fábrica, não retorna nada (retorna um objeto que contém métodos / propriedades).

app.service('MyService', function() {
    //directly binding events to this context
    this.myServiceFunction = function() {
        //TO DO:
    };
});

Uso

Use-o quando precisar compartilhar um único objeto em todo o aplicativo. Por exemplo, detalhes do usuário autenticado, métodos / dados compartilhados, funções do utilitário etc.

Fornecedor

Um provedor é usado para criar um objeto de serviço configurável. Você pode configurar a configuração de serviço a partir da função config. Ele retorna um valor usando a $get()função. A $getfunção é executada na fase de execução em angular.

app.provider('configurableService', function() {
    var name = '';
    //this method can be be available at configuration time inside app.config.
    this.setName = function(newName) {
        name = newName;
    };
    this.$get = function() {
        var getName = function() {
             return name;
        };
        return {
            getName: getName //exposed object to where it gets injected.
        };
    };
});

Uso

Quando você precisar fornecer configuração de módulo para seu objeto de serviço antes de disponibilizá-lo, por exemplo. suponha que você queira definir o seu URL API com base em seu ambiente como dev, stageouprod

NOTA

Apenas o provedor estará disponível na fase de configuração do angular, enquanto o serviço e a fábrica não estão.

Espero que isso tenha esclarecido sua compreensão sobre Fábrica, Serviço e Provedor .


Serviço vs provedor vs fábrica:

Estou tentando simplificar. É tudo sobre o conceito básico de JavaScript.

Primeiro de tudo, vamos falar sobre serviços no AngularJS!

O que é serviço: no AngularJS, Servicenão é nada além de um objeto JavaScript singleton que pode armazenar alguns métodos ou propriedades úteis. Este objeto singleton é criado por base ngApp (aplicativo Angular) e é compartilhado entre todos os controladores dentro do aplicativo atual. Quando Angularjs instancia um objeto de serviço, ele registra esse objeto de serviço com um nome de serviço exclusivo. Portanto, sempre que precisarmos de instância de serviço, o Angular pesquisará o registro desse nome de serviço e retornará a referência ao objeto de serviço. Tal que podemos invocar método, acessar propriedades etc no objeto de serviço. Você pode ter dúvidas se você também pode colocar propriedades, métodos no objeto de escopo de controladores! Então, por que você precisa de objeto de serviço? Respostas é: os serviços são compartilhados entre o escopo de múltiplos controladores. Se você colocar algumas propriedades / métodos no objeto de escopo de um controlador, ele estará disponível apenas para o escopo atual.Mas quando você define métodos, propriedades no objeto de serviço, ele estará disponível globalmente e pode ser acessado no escopo de qualquer controlador, injetando esse serviço.

Portanto, se houver três escopos de controlador, seja controladorA, controladorB e controladorC, todos compartilharão a mesma instância de serviço.

<div ng-controller='controllerA'>
    <!-- controllerA scope -->
</div>
<div ng-controller='controllerB'>
    <!-- controllerB scope -->
</div>
<div ng-controller='controllerC'>
    <!-- controllerC scope -->
</div>

Como criar um serviço?

O AngularJS fornece diferentes métodos para registrar um serviço. Aqui vamos nos concentrar em três métodos factory (..), service (..), provider (..);

Use este link para referência de código

Função de fábrica:

Podemos definir uma função de fábrica como abaixo.

factory('serviceName',function fnFactory(){ return serviceInstance;})

O AngularJS fornece o método 'factory (' serviceName ', fnFactory)' que recebe dois parâmetros, serviceName e uma função JavaScript. Angular cria instância de serviço invocando a função fnFactory () como abaixo.

var serviceInstace = fnFactory();

A função passada pode definir um objeto e retornar esse objeto. AngularJS simplesmente armazena esta referência de objeto para uma variável que é passada como primeiro argumento. Tudo o que é retornado de fnFactory será vinculado a serviceInstance. Em vez de retornar o objeto, também podemos retornar a função, os valores etc, o que quer que retornemos, estarão disponíveis para a instância de serviço.

Exemplo:

var app= angular.module('myApp', []);
//creating service using factory method
app.factory('factoryPattern',function(){
  var data={
    'firstName':'Tom',
    'lastName':' Cruise',
    greet: function(){
      console.log('hello!' + this.firstName + this.lastName);
    }
  };

  //Now all the properties and methods of data object will be available in our service object
  return data;
});

Função de serviço:

service('serviceName',function fnServiceConstructor(){})

É a outra maneira, podemos registrar um serviço. A única diferença é a maneira como o AngularJS tenta instanciar o objeto de serviço. Dessa vez, o angular usa a palavra-chave 'new' e chama a função de construtor de algo como abaixo.

var serviceInstance = new fnServiceConstructor();

Na função de construtor, podemos usar a palavra-chave 'this' para adicionar propriedades / métodos ao objeto de serviço. exemplo:

//Creating a service using the service method
var app= angular.module('myApp', []);
app.service('servicePattern',function(){
  this.firstName ='James';
  this.lastName =' Bond';
  this.greet = function(){
    console.log('My Name is '+ this.firstName + this.lastName);
  };
});

Função de provedor:

A função Provider () é a outra maneira de criar serviços. Deixe-nos interessados ​​em criar um serviço que apenas exiba alguma mensagem de saudação ao usuário. Mas também queremos fornecer uma funcionalidade para que o usuário possa definir sua própria mensagem de saudação. Em termos técnicos, queremos criar serviços configuráveis. Como podemos fazer isso ? Deve haver uma maneira, para que o aplicativo possa passar suas mensagens de saudação personalizadas e o Angularjs o disponibilizaria para a função de fábrica / construtor que cria nossa instância de serviços. Nesse caso, a função provider () faz o trabalho. Usando a função provider (), podemos criar serviços configuráveis.

Podemos criar serviços configuráveis ​​usando a sintaxe do provedor conforme abaixo.

/*step1:define a service */
app.provider('service',function serviceProviderConstructor(){});

/*step2:configure the service */
app.config(function configureService(serviceProvider){});

Como a sintaxe do provedor funciona internamente?

O objeto 1.Provider é criado usando a função construtora que definimos em nossa função de provedor.

var serviceProvider = new serviceProviderConstructor();

2.A função que passamos em app.config (), é executada. Isso é chamado de fase de configuração, e aqui temos a chance de personalizar nosso serviço.

configureService(serviceProvider);

3.Finalmente, a instância de serviço é criada chamando o método $ get do serviceProvider.

serviceInstance = serviceProvider.$get()

Exemplo de código para criar serviço usando a sintaxe de fornecimento:

var app= angular.module('myApp', []);
app.provider('providerPattern',function providerConstructor(){
  //this function works as constructor function for provider
  this.firstName = 'Arnold ';
  this.lastName = ' Schwarzenegger' ;
  this.greetMessage = ' Welcome, This is default Greeting Message' ;
  //adding some method which we can call in app.config() function
  this.setGreetMsg = function(msg){
    if(msg){
      this.greetMessage =  msg ;
    }
  };

  //We can also add a method which can change firstName and lastName
  this.$get = function(){
    var firstName = this.firstName;
    var lastName = this.lastName ;
    var greetMessage = this.greetMessage;
    var data={
       greet: function(){
         console.log('hello, ' + firstName + lastName+'! '+ greetMessage);
       }
    };
    return data ;
  };
});

app.config(
  function(providerPatternProvider){
    providerPatternProvider.setGreetMsg(' How do you do ?');
  }
);

Demonstração de Trabalho

Resumo:

Fábrica usa uma função de fábrica que retorna uma instância de serviço. serviceInstance = fnFactory ();

O serviço usa uma função construtora e o Angular invoca essa função construtora usando a palavra-chave 'new' para criar a instância do serviço. serviceInstance = novo fnServiceConstructor ();

O provedor define uma função providerConstructor, essa função providerConstructor define uma função de fábrica $ get . Angular chama $ get () para criar o objeto de serviço. A sintaxe do provedor tem uma vantagem adicional de configurar o objeto de serviço antes de ser instanciado. serviceInstance = $ get ();


TL; DR

1) Quando você está usando um Factory, você cria um objeto, adiciona propriedades a ele e retorna esse mesmo objeto. Quando você passa esta fábrica para o seu controlador, essas propriedades no objeto estarão disponíveis naquele controlador através de sua fábrica.

app.controller(‘myFactoryCtrl’, function($scope, myFactory){
  $scope.artist = myFactory.getArtist();
});

app.factory(‘myFactory’, function(){
  var _artist = ‘Shakira’;
  var service = {};

  service.getArtist = function(){
    return _artist;
  }

  return service;
});


2) Quando você está usando o serviço , o AngularJS instancia isso nos bastidores com a palavra-chave 'new'. Por causa disso, você adicionará propriedades a 'this' e o serviço retornará 'this'. Quando você passa o serviço para o seu controlador, essas propriedades no 'this' agora estarão disponíveis nesse controlador através do seu serviço.

app.controller(‘myServiceCtrl’, function($scope, myService){
  $scope.artist = myService.getArtist();
});

app.service(‘myService’, function(){
  var _artist = ‘Nelly’;
  this.getArtist = function(){
    return _artist;
  }
});



3) Provedores são o único serviço que você pode passar para a sua função .config (). Use um provedor quando desejar fornecer a configuração de todo o módulo para o seu objeto de serviço antes de disponibilizá-lo.

app.controller(‘myProvider’, function($scope, myProvider){
  $scope.artist = myProvider.getArtist();
  $scope.data.thingFromConfig = myProvider.thingOnConfig;
});

app.provider(‘myProvider’, function(){
 //Only the next two lines are available in the app.config()
 this._artist = ‘’;
 this.thingFromConfig = ‘’;
  this.$get = function(){
    var that = this;
    return {
      getArtist: function(){
        return that._artist;
      },
      thingOnConfig: that.thingFromConfig
    }
  }
});

app.config(function(myProviderProvider){
  myProviderProvider.thingFromConfig = ‘This was set in config’;
});



Não TL; DR

1) fábrica
As fábricas são a maneira mais popular de criar e configurar um serviço. Não há realmente muito mais do que o que o TL; DR disse. Você acabou de criar um objeto, adicionar propriedades a ele e retornar esse mesmo objeto. Então, quando você passar a fábrica para o seu controlador, essas propriedades no objeto estarão disponíveis naquele controlador através de sua fábrica. Um exemplo mais extenso está abaixo.

app.factory(‘myFactory’, function(){
  var service = {};
  return service;
});

Agora, quaisquer propriedades que anexarmos ao 'serviço' estarão disponíveis para nós quando passarmos 'myFactory' para o nosso controlador.

Agora vamos adicionar algumas variáveis ​​'privadas' à nossa função de retorno de chamada. Estes não serão diretamente acessíveis a partir do controlador, mas eventualmente criaremos alguns métodos getter / setter em 'service' para podermos alterar essas variáveis ​​'privadas' quando necessário.

app.factory(‘myFactory’, function($http, $q){
  var service = {};
  var baseUrl = ‘https://itunes.apple.com/search?term=’;
  var _artist = ‘’;
  var _finalUrl = ‘’;

  var makeUrl = function(){
   _artist = _artist.split(‘ ‘).join(‘+’);
    _finalUrl = baseUrl + _artist + ‘&callback=JSON_CALLBACK’;
    return _finalUrl
  }

  return service;
});

Aqui você notará que não estamos anexando essas variáveis ​​/ função ao 'serviço'. Estamos simplesmente criando-os para usá-los ou modificá-los mais tarde.

  • baseUrl é o URL base que a API do iTunes exige
  • _artist é o artista que desejamos pesquisar
  • _finalUrl é o URL final e totalmente construído para o qual faremos a chamada para o iTunes
  • O makeUrl é uma função que irá criar e devolver o nosso URL do iTunes.

Agora que as variáveis ​​e funções do helper / private estão no lugar, vamos adicionar algumas propriedades ao objeto 'service'. Tudo o que colocarmos em 'serviço' pode ser usado diretamente dentro do controlador pelo qual passamos 'myFactory'.

Vamos criar métodos setArtist e getArtist que simplesmente retornam ou configuram o artista. Também vamos criar um método que irá chamar a API do iTunes com o nosso URL criado. Esse método retornará uma promessa que será cumprida assim que os dados forem retornados da API do iTunes. Se você não tem muita experiência em usar promessas no AngularJS, eu recomendo dar um mergulho profundo nelas.

Abaixo de setArtist aceita um artista e permite que você defina o artista. getArtist retorna o artista. O callItunes primeiro chama o makeUrl () para construir o URL que usaremos com o nosso pedido $ http. Em seguida, ele configura um objeto de promessa, faz uma solicitação de $ http com nosso URL final e, em seguida, porque $ http retorna uma promessa, podemos chamar .success ou .error após nossa solicitação. Em seguida, resolvemos nossa promessa com os dados do iTunes ou a rejeitamos com uma mensagem dizendo "Ocorreu um erro".

app.factory('myFactory', function($http, $q){
  var service = {};
  var baseUrl = 'https://itunes.apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }

  service.setArtist = function(artist){
    _artist = artist;
  }

  service.getArtist = function(){
    return _artist;
  }

  service.callItunes = function(){
    makeUrl();
    var deferred = $q.defer();
    $http({
      method: 'JSONP',
      url: _finalUrl
    }).success(function(data){
      deferred.resolve(data);
    }).error(function(){
      deferred.reject('There was an error')
    })
    return deferred.promise;
  }

  return service;
});

Agora nossa fábrica está completa. Agora podemos injetar 'myFactory' em qualquer controlador e então poderemos chamar nossos métodos que anexamos ao nosso objeto de serviço (setArtist, getArtist e callItunes).

app.controller('myFactoryCtrl', function($scope, myFactory){
  $scope.data = {};
  $scope.updateArtist = function(){
    myFactory.setArtist($scope.data.artist);
  };

  $scope.submitArtist = function(){
    myFactory.callItunes()
      .then(function(data){
        $scope.data.artistData = data;
      }, function(data){
        alert(data);
      })
  }
});

No controlador acima, estamos injetando no serviço 'myFactory'. Em seguida, definimos propriedades em nosso objeto $ escopo com dados de 'myFactory'. O único código complicado acima é se você nunca lidou com promessas antes. Como o callItunes está retornando uma promessa, podemos usar o método .then () e definir somente $ scope.data.artistData quando nossa promessa for cumprida com os dados do iTunes. Você notará que o nosso controlador é muito 'fino' (esta é uma boa prática de codificação). Toda a nossa lógica e dados persistentes estão localizados em nosso serviço, não em nosso controlador.

2) serviço
Talvez a coisa mais importante a saber ao lidar com a criação de um serviço seja que ele seja instanciado com a palavra-chave "novo". Para você, gurus do JavaScript, isso deve lhe dar uma grande dica sobre a natureza do código. Para aqueles com um histórico limitado em JavaScript ou para aqueles que não estão muito familiarizados com o que a "nova" palavra-chave realmente faz, vamos revisar alguns fundamentos JavaScript que eventualmente nos ajudarão a entender a natureza de um Serviço.

Para realmente ver as mudanças que ocorrem quando você invoca uma função com a palavra-chave 'new', vamos criar uma função e chamá-la com a palavra-chave 'new', então vamos mostrar o que o interpretador faz quando vê a palavra-chave 'new'. Os resultados finais serão os mesmos.

Primeiro vamos criar nosso construtor.

var Person = function(name, age){
  this.name = name;
  this.age = age;
}

Esta é uma função típica do construtor de JavaScript. Agora, sempre que invocarmos a função Person usando a palavra-chave 'new', 'this' será vinculado ao objeto recém-criado.

Agora vamos adicionar um método ao protótipo de nossa pessoa, para que ele esteja disponível em todas as instâncias de nossa "classe" pessoal.

Person.prototype.sayName = function(){
  alert(‘My name is ‘ + this.name);
}

Agora, como colocamos a função sayName no protótipo, cada instância de Person poderá chamar a função sayName para alertar o nome dessa instância.

Agora que temos nossa função construtora Person e nossa função sayName em seu protótipo, vamos criar uma instância de Person e chamar a função sayName.

var tyler = new Person(‘Tyler’, 23);
tyler.sayName(); //alerts ‘My name is Tyler’

Então, todos juntos, o código para criar um construtor Person, adicionando uma função ao seu protótipo, criando uma instância Person e, em seguida, chamando a função em seu protótipo se parece com isso.

var Person = function(name, age){
  this.name = name;
  this.age = age;
}
Person.prototype.sayName = function(){
  alert(‘My name is ‘ + this.name);
}
var tyler = new Person(‘Tyler’, 23);
tyler.sayName(); //alerts ‘My name is Tyler’

Agora vamos ver o que realmente está acontecendo quando você usa a palavra-chave 'new' em JavaScript. A primeira coisa que você deve notar é que depois de usar 'novo' em nosso exemplo, podemos chamar um método (sayName) em 'tyler' como se fosse um objeto - é porque é. Então, primeiro, sabemos que nosso construtor Person está retornando um objeto, se podemos ver isso no código ou não. Segundo, sabemos que, como nossa função sayName está localizada no protótipo e não diretamente na instância Person, o objeto que a função Person está retornando deve estar delegando a seu protótipo em pesquisas com falha. Em termos mais simples, quando chamamos tyler.sayName (), o interpretador diz “OK, vou olhar o objeto 'tyler' que acabamos de criar, localize a função sayName e, em seguida, chame-o. Espere um minuto, não vejo aqui - tudo que vejo é nome e idade, deixe-me verificar o protótipo. Sim, parece que está no protótipo, deixe-me chamá-lo ”.

Abaixo está o código de como você pode pensar sobre o que a 'nova palavra-chave' está realmente fazendo em JavaScript. É basicamente um exemplo de código do parágrafo acima. Eu coloquei a 'visão de intérprete' ou a maneira como o intérprete vê o código dentro das notas.

var Person = function(name, age){
  //The below line creates an object(obj) that will delegate to the person’s prototype on failed lookups.
  //var obj = Object.create(Person.prototype);

  //The line directly below this sets ‘this’ to the newly created object
  //this = obj;

  this.name = name;
  this.age = age;

  //return this;
}

Agora, tendo esse conhecimento do que a palavra-chave 'new' realmente faz no JavaScript, criar um serviço no AngularJS deve ser mais fácil de entender.

A maior coisa a entender ao criar um Serviço é saber que os Serviços são instanciados com a palavra-chave 'new'. Combinando esse conhecimento com nossos exemplos acima, você deve reconhecer que estará anexando suas propriedades e métodos diretamente a 'this', que será então retornado do próprio Serviço. Vamos dar uma olhada nisso em ação.

Ao contrário do que fizemos originalmente com o exemplo Factory, não precisamos criar um objeto e, em seguida, retornar esse objeto porque, como mencionado muitas vezes antes, usamos a palavra-chave 'new' para que o interpretador crie esse objeto, tenha ele delegado para é protótipo, depois devolva para nós sem que tenhamos que fazer o trabalho.

Primeiras coisas primeiro, vamos criar nossa função 'privada' e auxiliar. Isso deve parecer muito familiar, já que fizemos exatamente a mesma coisa com nossa fábrica. Não vou explicar o que cada linha faz aqui porque eu fiz isso no exemplo da fábrica, se você está confuso, releia o exemplo da fábrica.

app.service('myService', function($http, $q){
  var baseUrl = 'https://itunes.apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }
});

Agora, vamos anexar todos os nossos métodos que estarão disponíveis em nosso controller para 'this'.

app.service('myService', function($http, $q){
  var baseUrl = 'https://itunes.apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }

  this.setArtist = function(artist){
    _artist = artist;
  }

  this.getArtist = function(){
    return _artist;
  }

  this.callItunes = function(){
    makeUrl();
    var deferred = $q.defer();
    $http({
      method: 'JSONP',
      url: _finalUrl
    }).success(function(data){
      deferred.resolve(data);
    }).error(function(){
      deferred.reject('There was an error')
    })
    return deferred.promise;
  }

});

Agora, assim como em nossa fábrica, setArtist, getArtist e callItunes estarão disponíveis em qualquer controlador em que passemos o myService. Aqui está o controlador myService (que é quase exatamente o mesmo que o nosso controlador de fábrica).

app.controller('myServiceCtrl', function($scope, myService){
  $scope.data = {};
  $scope.updateArtist = function(){
    myService.setArtist($scope.data.artist);
  };

  $scope.submitArtist = function(){
    myService.callItunes()
      .then(function(data){
        $scope.data.artistData = data;
      }, function(data){
        alert(data);
      })
  }
});

Como eu mencionei antes, uma vez que você realmente entende o que 'novo' faz, os Serviços são quase idênticos às fábricas do AngularJS.

3) Provedor

A coisa mais importante a lembrar sobre Providers é que eles são o único serviço que você pode passar para a parte app.config do seu aplicativo. Isso é de grande importância se você precisar alterar alguma parte do objeto de serviço antes de estar disponível em qualquer outro lugar do aplicativo. Embora muito semelhante aos Serviços / Fábricas, existem algumas diferenças que discutiremos.

Primeiro, configuramos nosso Provedor da mesma maneira que fizemos com nosso Serviço e Fábrica. As variáveis ​​abaixo são nossa função 'privada' e auxiliar.

app.provider('myProvider', function(){
   var baseUrl = 'https://itunes.apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  //Going to set this property on the config function below.
  this.thingFromConfig = ‘’;

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }
}

* Novamente, se qualquer parte do código acima for confusa, confira a seção Factory, onde eu explico o que tudo isso faz com maiores detalhes.

Você pode pensar em provedores como tendo três seções. A primeira seção é as variáveis ​​/ funções 'privadas' que serão modificadas / configuradas posteriormente (mostradas acima). A segunda seção são as variáveis ​​/ funções que estarão disponíveis na sua função app.config e, portanto, estão disponíveis para serem alteradas antes de estarem disponíveis em qualquer outro lugar (também mostrado acima). É importante observar que essas variáveis ​​precisam ser anexadas à palavra-chave 'this'. Em nosso exemplo, apenas 'thingFromConfig' estará disponível para alteração no app.config. A terceira seção (mostrada abaixo) é todas as variáveis ​​/ funções que estarão disponíveis no seu controlador quando você passa no serviço 'myProvider' para aquele controlador específico.

Ao criar um serviço com o Provedor, as únicas propriedades / métodos que estarão disponíveis em seu controlador são aquelas propriedades / métodos que são retornados da função $ get (). O código abaixo coloca $ get on 'this' (que sabemos que eventualmente será retornado dessa função). Agora, essa função $ get retorna todos os métodos / propriedades que queremos estar disponíveis no controlador. Aqui está um exemplo de código.

this.$get = function($http, $q){
    return {
      callItunes: function(){
        makeUrl();
        var deferred = $q.defer();
        $http({
          method: 'JSONP',
          url: _finalUrl
        }).success(function(data){
          deferred.resolve(data);
        }).error(function(){
          deferred.reject('There was an error')
        })
        return deferred.promise;
      },
      setArtist: function(artist){
        _artist = artist;
      },
      getArtist: function(){
        return _artist;
      },
      thingOnConfig: this.thingFromConfig
    }
  }

Agora, o código completo do provedor se parece com isso

app.provider('myProvider', function(){
  var baseUrl = 'https://itunes.apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  //Going to set this property on the config function below
  this.thingFromConfig = '';

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }

  this.$get = function($http, $q){
    return {
      callItunes: function(){
        makeUrl();
        var deferred = $q.defer();
        $http({
          method: 'JSONP',
          url: _finalUrl
        }).success(function(data){
          deferred.resolve(data);
        }).error(function(){
          deferred.reject('There was an error')
        })
        return deferred.promise;
      },
      setArtist: function(artist){
        _artist = artist;
      },
      getArtist: function(){
        return _artist;
      },
      thingOnConfig: this.thingFromConfig
    }
  }
});

Agora, assim como em nossa fábrica e serviço, setArtist, getArtist e callItunes estarão disponíveis em qualquer controlador em que passemos myProvider. Aqui está o controlador myProvider (que é quase exatamente o mesmo que nosso controlador de fábrica / serviço).

app.controller('myProviderCtrl', function($scope, myProvider){
  $scope.data = {};
  $scope.updateArtist = function(){
    myProvider.setArtist($scope.data.artist);
  };

  $scope.submitArtist = function(){
    myProvider.callItunes()
      .then(function(data){
        $scope.data.artistData = data;
      }, function(data){
        alert(data);
      })
  }

  $scope.data.thingFromConfig = myProvider.thingOnConfig;
});

Como mencionado anteriormente, o objetivo de criar um serviço com Provider é poder alterar algumas variáveis ​​por meio da função app.config antes que o objeto final seja passado para o restante do aplicativo. Vamos ver um exemplo disso.

app.config(function(myProviderProvider){
  //Providers are the only service you can pass into app.config
  myProviderProvider.thingFromConfig = 'This sentence was set in app.config. Providers are the only service that can be passed into config. Check out the code to see how it works';
});

Agora você pode ver como 'thingFromConfig' é uma string vazia em nosso provedor, mas quando isso aparecer no DOM, será 'Esta sentença foi configurada…'.


Esta é uma parte muito confusa para o novato e eu tentei esclarecê-lo em palavras fáceis

AngularJS Service: é usado para compartilhar funções de utilidade com a referência de serviço no controlador. O serviço é singleton na natureza, portanto, para um serviço, apenas uma instância é criada no navegador e a mesma referência é usada em toda a página.

No serviço, criamos nomes de função como propriedade com este objeto.

AngularJS Factory: o propósito de Factory também é o mesmo que Service, mas neste caso nós criamos um novo objeto e adicionamos funções como propriedades deste objeto e no final retornamos este objeto.

AngularJS Provider: o propósito disto é novamente o mesmo, no entanto o Provider fornece a saída da sua função $ get.

Definir e usar o serviço, fábrica e provedor são explicados em http://www.dotnetfunda.com/articles/show/3156/difference-between-angularjs-service-factory-and-provider


Esta resposta aborda o tópico / questão

como Fábrica, Serviço e Constante - são apenas açúcar sintático sobre uma receita de provedor?

OU

como fábrica, serviços e provedores são internamente internamente

basicamente o que acontece é

Quando você faz um factory()conjunto que você functionforneceu no segundo argumento para o provedor $gete retorna ele ( provider(name, {$get:factoryFn })), tudo que você obtém é, providermas não há nenhuma propriedade / método diferente$get daquele provider(significa que você não pode configurar isto)

Código fonte da fábrica

function factory(name, factoryFn, enforce) {
    return provider(name, {
      $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
    });
};

Ao fazer um service()retorno você fornece uma factory () com um functionque injeta o constructor(retorna a instância do construtor que você forneceu em seu serviço) e retorna-o

Código fonte de serviço

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

Então, basicamente, em ambos os casos, você finalmente obtém os provedores $ configurados para a sua função que você forneceu, mas você pode dar algo extra que $ get como você pode fornecer originalmente no provider () para o bloco de configuração


Já existem boas respostas, mas eu só quero compartilhar essa.

Primeiro de tudo: Provider é o caminho / receita para criar um service(objeto singleton) que suponha ser injetado pelo $ injector (como o AngulaJS segue o padrão IoC).

E Valor, Fábrica, Serviço e Constante (4 maneiras) - o açúcar sintático sobre o modo provedor / recepie.

Há uma Service vs Factoryparte foi coberta: https://www.youtube.com/watch?v=BLzNCkPn3ao

O serviço tem tudo a ver com newpalavras-chave que, como sabemos, faz 4 coisas:

  1. cria novo objeto
  2. liga-lo ao seu prototypeobjeto
  3. conecta context- se athis
  4. e retorna this

E Factory é toda sobre Padrão de Fábrica - contém funções que retornam Objetos como esse Serviço.

  1. capacidade de usar outros serviços (tem dependências)
  2. inicialização de serviço
  3. inicialização atrasada / lenta

E este simples / curto vídeo: abrange também Provedor : https://www.youtube.com/watch?v=HvTZbQ_hUZY (lá você vê pode ver como eles vão de fábrica para provedor)

A receita do provedor é usada principalmente na configuração do aplicativo, antes que o aplicativo seja totalmente iniciado / inicializado.


Meu entendimento é muito simples abaixo.

Fábrica: basta criar um objeto dentro da fábrica e devolvê-lo.

Serviço:

Você só tem uma função padrão que usa essa palavra-chave para definir uma função.

Fornecedor:

Existe um $getobjeto que você define e pode ser usado para obter o objeto que retorna dados.


Para mim, a melhor e mais simples maneira de entender a diferença é:

var service, factory;
service = factory = function(injection) {}

Como o AngularJS instancia componentes específicos (simplificados):

// service
var angularService = new service(injection);

// factory
var angularFactory = factory(injection);

Assim, para o serviço, o que se torna o componente AngularJS é a instância do objeto da classe que é representada pela função de declaração de serviço. Para a fábrica, é o resultado retornado da função de declaração de fábrica. A fábrica pode se comportar da mesma forma que o serviço:

var factoryAsService = function(injection) {
  return new function(injection) {
    // Service content
  }
}

A maneira mais simples de pensar é a seguinte:

  • Serviço é uma instância de objeto singleton. Use serviços se você quiser fornecer um objeto singleton para seu código.
  • Fábrica é uma aula. Use factories se você quiser fornecer classes customizadas para seu código (não pode ser feito com serviços porque elas já estão instanciadas).

O exemplo de 'classe' da fábrica é fornecido nos comentários, bem como na diferença do provedor.


Só para esclarecer as coisas, a partir da fonte AngularJS, você pode ver que um serviço apenas chama a função de fábrica que, por sua vez, chama a função de provedor:

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

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

Aqui está um código que eu criei como um modelo de código para fábrica de objetos no AngularjS. Eu usei um Car / CarFactory como um exemplo para ilustrar. Faz o código de implementação simples no controlador.

     <script>
        angular.module('app', [])
            .factory('CarFactory', function() {

                /**
                 * BroilerPlate Object Instance Factory Definition / Example
                 */
                this.Car = function() {

                    // initialize instance properties
                    angular.extend(this, {
                        color           : null,
                        numberOfDoors   : null,
                        hasFancyRadio   : null,
                        hasLeatherSeats : null
                    });

                    // generic setter (with optional default value)
                    this.set = function(key, value, defaultValue, allowUndefined) {

                        // by default,
                        if (typeof allowUndefined === 'undefined') {
                            // we don't allow setter to accept "undefined" as a value
                            allowUndefined = false;
                        }
                        // if we do not allow undefined values, and..
                        if (!allowUndefined) {
                            // if an undefined value was passed in
                            if (value === undefined) {
                                // and a default value was specified
                                if (defaultValue !== undefined) {
                                    // use the specified default value
                                    value = defaultValue;
                                } else {
                                    // otherwise use the class.prototype.defaults value
                                    value = this.defaults[key];
                                } // end if/else
                            } // end if
                        } // end if

                        // update 
                        this[key] = value;

                        // return reference to this object (fluent)
                        return this;

                    }; // end this.set()

                }; // end this.Car class definition

                // instance properties default values
                this.Car.prototype.defaults = {
                    color: 'yellow',
                    numberOfDoors: 2,
                    hasLeatherSeats: null,
                    hasFancyRadio: false
                };

                // instance factory method / constructor
                this.Car.prototype.instance = function(params) {
                    return new 
                        this.constructor()
                                .set('color',           params.color)
                                .set('numberOfDoors',   params.numberOfDoors)
                                .set('hasFancyRadio',   params.hasFancyRadio)
                                .set('hasLeatherSeats', params.hasLeatherSeats)
                    ;
                };

                return new this.Car();

            }) // end Factory Definition
            .controller('testCtrl', function($scope, CarFactory) {

                window.testCtrl = $scope;

                // first car, is red, uses class default for:
                // numberOfDoors, and hasLeatherSeats
                $scope.car1     = CarFactory
                                    .instance({
                                        color: 'red'
                                    })
                                ;

                // second car, is blue, has 3 doors, 
                // uses class default for hasLeatherSeats
                $scope.car2     = CarFactory
                                    .instance({
                                        color: 'blue',
                                        numberOfDoors: 3
                                    })
                                ;
                // third car, has 4 doors, uses class default for 
                // color and hasLeatherSeats
                $scope.car3     = CarFactory
                                    .instance({
                                        numberOfDoors: 4
                                    })
                                ;
                // sets an undefined variable for 'hasFancyRadio',
                // explicitly defines "true" as default when value is undefined
                $scope.hasFancyRadio = undefined;
                $scope.car3.set('hasFancyRadio', $scope.hasFancyRadio, true);

                // fourth car, purple, 4 doors,
                // uses class default for hasLeatherSeats
                $scope.car4     = CarFactory
                                    .instance({
                                        color: 'purple',
                                        numberOfDoors: 4
                                    });
                // and then explicitly sets hasLeatherSeats to undefined
                $scope.hasLeatherSeats = undefined;
                $scope.car4.set('hasLeatherSeats', $scope.hasLeatherSeats, undefined, true);

                // in console, type window.testCtrl to see the resulting objects

            });
    </script>

Aqui está um exemplo mais simples. Estou usando algumas bibliotecas de terceiros que esperam que um objeto "Posição" exponha latitude e longitude, mas por meio de diferentes propriedades de objeto. Eu não queria hackear o código do fornecedor, então ajustei os objetos "Position" que eu estava passando.

    angular.module('app')
.factory('PositionFactory', function() {

    /**
     * BroilerPlate Object Instance Factory Definition / Example
     */
    this.Position = function() {

        // initialize instance properties 
        // (multiple properties to satisfy multiple external interface contracts)
        angular.extend(this, {
            lat         : null,
            lon         : null,
            latitude    : null,
            longitude   : null,
            coords: {
                latitude: null,
                longitude: null
            }
        });

        this.setLatitude = function(latitude) {
            this.latitude           = latitude;
            this.lat                = latitude;
            this.coords.latitude    = latitude;
            return this;
        };
        this.setLongitude = function(longitude) {
            this.longitude          = longitude;
            this.lon                = longitude;
            this.coords.longitude   = longitude;
            return this;
        };

    }; // end class definition

    // instance factory method / constructor
    this.Position.prototype.instance = function(params) {
        return new 
            this.constructor()
                    .setLatitude(params.latitude)
                    .setLongitude(params.longitude)
        ;
    };

    return new this.Position();

}) // end Factory Definition

.controller('testCtrl', function($scope, PositionFactory) {
    $scope.position1 = PositionFactory.instance({latitude: 39, longitude: 42.3123});
    $scope.position2 = PositionFactory.instance({latitude: 39, longitude: 42.3333});
}) // end controller

;


Com base em propósitos de memória, os controladores são instanciados somente quando são necessários e descartados quando não são. Devido a isso, toda vez que você alterna uma rota ou recarrega uma página, o Angular limpa o controlador atual. No entanto, os serviços fornecem um meio de manter os dados por toda a vida útil de um aplicativo, enquanto eles também podem ser usados ​​em diferentes controladores de maneira consistente.

Angular nos fornece três maneiras de criar e registrar nosso próprio serviço.

1) fábrica

2) serviço

3) Provedor

Fábrica : Uma fábrica é uma função simples que permite adicionar alguma lógica antes de criar o objeto. Ele retorna o objeto criado.

É apenas uma coleção de funções como uma classe. Portanto, ele pode ser instanciado em diferentes controladores quando você o estiver usando com a função de construtor.

Serviço : Um serviço é uma função construtora que cria o objeto usando uma nova palavra-chave. Você pode adicionar propriedades e funções a um objeto de serviço usando essa palavra-chave. Ao contrário da fábrica, não retorna nada.

É um objeto singleton. Use-o quando precisar compartilhar um único objeto no aplicativo. Por exemplo, detalhes do usuário autenticado.

Provedor : um provedor é usado para criar um objeto de serviço configurável. Ele retorna valor usando a função $ get ().

Quando você precisa fornecer uma configuração baseada em módulo para seu objeto de serviço antes de disponibilizá-lo.

Execute o seguinte código e veja a saída.

<!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>


Essencialmente, Provedor, Fábrica e Serviço são todos os Serviços. Uma Fábrica é um caso especial de um Serviço quando tudo o que você precisa é de uma função $ get (), permitindo que você o escreva com menos código.

As principais diferenças entre Serviços, Fábricas e Provedores são suas complexidades. Os serviços são a forma mais simples, as Fábricas são um pouco mais robustas e os Provedores são configuráveis ​​em tempo de execução.

Aqui está um resumo de quando usar cada um:

Fábrica : o valor que você está fornecendo precisa ser calculado com base em outros dados.

Serviço : Você está retornando um objeto com métodos.

Provedor : Você quer ser capaz de configurar, durante a fase de configuração, o objeto que será criado antes de ser criado. Use o Provedor principalmente na configuração do aplicativo, antes que o aplicativo seja totalmente inicializado.


Eu sei muita resposta excelente, mas eu tenho que compartilhar minha experiência de usar
1. servicepara a maioria dos casos de padrão
2. factoryusado para criar o serviço que instância específica

// factory.js ////////////////////////////
(function() {
'use strict';
angular
    .module('myApp.services')
    .factory('xFactory', xFactoryImp);
xFactoryImp.$inject = ['$http'];

function xFactoryImp($http) {
    var fac = function (params) {
        this._params = params; // used for query params
    };

    fac.prototype.nextPage = function () {
        var url = "/_prc";

        $http.get(url, {params: this._params}).success(function(data){ ...
    }
    return fac;
}
})();

// service.js //////////////////////////
(function() {
'use strict';
angular
    .module('myApp.services')
    .service('xService', xServiceImp);
xServiceImp.$inject = ['$http'];

function xServiceImp($http) {  
    this._params = {'model': 'account','mode': 'list'};

    this.nextPage = function () {
        var url = "/_prc";

        $http.get(url, {params: this._params}).success(function(data){ ...
    }       
}
})();

e usando:

controller: ['xFactory', 'xService', function(xFactory, xService){

        // books = new instance of xFactory for query 'book' model
        var books = new xFactory({'model': 'book', 'mode': 'list'});

        // accounts = new instance of xFactory for query 'accounts' model
        var accounts = new xFactory({'model': 'account', 'mode': 'list'});

        // accounts2 = accounts variable
        var accounts2 = xService;
... 

Pouco atrasado para a festa. Mas achei que isso é mais útil para quem gostaria de aprender (ou ter clareza) sobre o desenvolvimento de serviços personalizados do Angular JS usando metodologias de fábrica, serviço e provedor.

Eu me deparei com este vídeo que explica claramente as metodologias de fábrica, serviço e provedor para desenvolver serviços personalizados AngularJS:

https://www.youtube.com/watch?v=oUXku28ex-M

Código Fonte: http://www.techcbt.com/Post/353/Angular-JS-basics/how-to-develop-angularjs-custom-service

O código postado aqui é copiado diretamente da fonte acima, para beneficiar os leitores.

O código para o serviço personalizado baseado em "fábrica" ​​é o seguinte (que acompanha as versões sync e async junto com o serviço http de chamada):

var app = angular.module("app", []);
app.controller('emp', ['$scope', 'calcFactory',
  function($scope, calcFactory) {
    $scope.a = 10;
    $scope.b = 20;

    $scope.doSum = function() {
      //$scope.sum = calcFactory.getSum($scope.a, $scope.b); //synchronous
      calcFactory.getSum($scope.a, $scope.b, function(r) { //aynchronous
        $scope.sum = r;
      });
    };

  }
]);

app.factory('calcFactory', ['$http', '$log',
  function($http, $log) {
    $log.log("instantiating calcFactory..");
    var oCalcService = {};

    //oCalcService.getSum = function(a,b){
    //	return parseInt(a) + parseInt(b);
    //};

    //oCalcService.getSum = function(a, b, cb){
    //	var s = parseInt(a) + parseInt(b);
    //	cb(s);
    //};

    oCalcService.getSum = function(a, b, cb) { //using http service

      $http({
        url: 'http://localhost:4467/Sum?a=' + a + '&b=' + b,
        method: 'GET'
      }).then(function(resp) {
        $log.log(resp.data);
        cb(resp.data);
      }, function(resp) {
        $log.error("ERROR occurred");
      });
    };

    return oCalcService;
  }
]);

O código da metodologia "service" para Custom Services (isto é bem parecido com 'factory', mas diferente do ponto de vista da sintaxe):

var app = angular.module("app", []);
app.controller('emp', ['$scope', 'calcService', function($scope, calcService){
	$scope.a = 10;
	$scope.b = 20;

	$scope.doSum = function(){
		//$scope.sum = calcService.getSum($scope.a, $scope.b);
		
		calcService.getSum($scope.a, $scope.b, function(r){
			$scope.sum = r;
		});		
	};

}]);

app.service('calcService', ['$http', '$log', function($http, $log){
	$log.log("instantiating calcService..");
	
	//this.getSum = function(a,b){
	//	return parseInt(a) + parseInt(b);
	//};

	//this.getSum = function(a, b, cb){
	//	var s = parseInt(a) + parseInt(b);
	//	cb(s);
	//};

	this.getSum = function(a, b, cb){
		$http({
			url: 'http://localhost:4467/Sum?a=' + a + '&b=' + b,
			method: 'GET'
		}).then(function(resp){
			$log.log(resp.data);
			cb(resp.data);
		},function(resp){
			$log.error("ERROR occurred");
		});
	};

}]);

O código da metodologia "provedor" para Serviços Personalizados (isso é necessário, se você quiser desenvolver um serviço que possa ser configurado):

var app = angular.module("app", []);
app.controller('emp', ['$scope', 'calcService', function($scope, calcService){
	$scope.a = 10;
	$scope.b = 20;

	$scope.doSum = function(){
		//$scope.sum = calcService.getSum($scope.a, $scope.b);
		
		calcService.getSum($scope.a, $scope.b, function(r){
			$scope.sum = r;
		});		
	};

}]);

app.provider('calcService', function(){

	var baseUrl = '';

	this.config = function(url){
		baseUrl = url;
	};

	this.$get = ['$log', '$http', function($log, $http){
		$log.log("instantiating calcService...")
		var oCalcService = {};

		//oCalcService.getSum = function(a,b){
		//	return parseInt(a) + parseInt(b);
		//};

		//oCalcService.getSum = function(a, b, cb){
		//	var s = parseInt(a) + parseInt(b);
		//	cb(s);	
		//};

		oCalcService.getSum = function(a, b, cb){

			$http({
				url: baseUrl + '/Sum?a=' + a + '&b=' + b,
				method: 'GET'
			}).then(function(resp){
				$log.log(resp.data);
				cb(resp.data);
			},function(resp){
				$log.error("ERROR occurred");
			});
		};		

		return oCalcService;
	}];

});

app.config(['calcServiceProvider', function(calcServiceProvider){
	calcServiceProvider.config("http://localhost:4467");
}]);

Finalmente, a interface do usuário que funciona com qualquer um dos serviços acima:

<html>
<head>
	<title></title>
	<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js" ></script>
	<script type="text/javascript" src="t03.js"></script>
</head>
<body ng-app="app">
	<div ng-controller="emp">
		<div>
			Value of a is {{a}},
			but you can change
			<input type=text ng-model="a" /> <br>

			Value of b is {{b}},
			but you can change
			<input type=text ng-model="b" /> <br>

		</div>
		Sum = {{sum}}<br>
		<button ng-click="doSum()">Calculate</button>
	</div>
</body>
</html>


Resumo de docs.angularjs.org/guide/providers :

  • Existem cinco tipos de receita que definem como criar objetos: Value , Factory , Service , Provider e Constant .
  • Fábrica e Serviço são as receitas mais usadas. A única diferença entre eles é que a receita de serviço funciona melhor para objetos de um tipo personalizado, enquanto o Factory pode produzir primitivas e funções de JavaScript.
  • A receita do provedor é o tipo de receita principal e todos os outros são apenas açúcar sintático.
  • Provedor é o tipo de receita mais complexo. Você não precisa disso, a menos que esteja criando um código reutilizável que precise de configuração global.

Melhores respostas do SO:

https://.com/a/26924234/165673 (<- GOOD) https://.com/a/27263882/165673
https://.com/a/16566144/165673


Um esclarecimento adicional é que as fábricas podem criar funções / primitivos, enquanto os serviços não podem. Confira este jsFiddle baseado no Epokk: http://jsfiddle.net/skeller88/PxdSP/1351/ .

A fábrica retorna uma função que pode ser chamada:

myApp.factory('helloWorldFromFactory', function() {
  return function() {
    return "Hello, World!";
  };
});

A fábrica também pode retornar um objeto com um método que pode ser chamado:

myApp.factory('helloWorldFromFactory', function() {
  return {
    sayHello: function() {
      return "Hello, World!";
    }
  };
});

O serviço retorna um objeto com um método que pode ser chamado:

myApp.service('helloWorldFromService', function() {
  this.sayHello = function() {
     return "Hello, World!";
  };
});

Para mais detalhes, veja um post que escrevi sobre a diferença: http://www.shanemkeller.com/tldr-services-vs-factories-in-angular/


Usando como referência esta página e a docs.angularjs.org/guide/providers (que parece ter melhorado muito desde a última vez que eu olhei), eu coloquei a seguinte demo mundial real (-ish) que usa 4 dos 5 sabores do provedor; Valor, Constante, Fábrica e Provedor completo.

HTML:

<div ng-controller="mainCtrl as main">
    <h1>{{main.title}}*</h1>
    <h2>{{main.strapline}}</h2>
    <p>Earn {{main.earn}} per click</p>
    <p>You've earned {{main.earned}} by clicking!</p>
    <button ng-click="main.handleClick()">Click me to earn</button>
    <small>* Not actual money</small>
</div>

aplicativo

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

// A CONSTANT is not going to change
app.constant('range', 100);

// A VALUE could change, but probably / typically doesn't
app.value('title', 'Earn money by clicking');
app.value('strapline', 'Adventures in ng Providers');

// A simple FACTORY allows us to compute a value @ runtime.
// Furthermore, it can have other dependencies injected into it such
// as our range constant.
app.factory('random', function randomFactory(range) {
    // Get a random number within the range defined in our CONSTANT
    return Math.random() * range;
});

// A PROVIDER, must return a custom type which implements the functionality 
// provided by our service (see what I did there?).
// Here we define the constructor for the custom type the PROVIDER below will 
// instantiate and return.
var Money = function(locale) {

    // Depending on locale string set during config phase, we'll
    // use different symbols and positioning for any values we 
    // need to display as currency
    this.settings = {
        uk: {
            front: true,
            currency: '£',
            thousand: ',',
            decimal: '.'
        },
        eu: {
            front: false,
            currency: '€',
            thousand: '.',
            decimal: ','
        }
    };

    this.locale = locale;
};

// Return a monetary value with currency symbol and placement, and decimal 
// and thousand delimiters according to the locale set in the config phase.
Money.prototype.convertValue = function(value) {

    var settings = this.settings[this.locale],
        decimalIndex, converted;

    converted = this.addThousandSeparator(value.toFixed(2), settings.thousand);

    decimalIndex = converted.length - 3;

    converted = converted.substr(0, decimalIndex) +
        settings.decimal +
        converted.substr(decimalIndex + 1);    

    converted = settings.front ?
            settings.currency + converted : 
            converted + settings.currency; 

    return converted;   
};

// Add supplied thousand separator to supplied value
Money.prototype.addThousandSeparator = function(value, symbol) {
   return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, symbol);
};

// PROVIDER is the core recipe type - VALUE, CONSTANT, SERVICE & FACTORY
// are all effectively syntactic sugar built on top of the PROVIDER construct
// One of the advantages of the PROVIDER is that we can configure it before the
// application starts (see config below).
app.provider('money', function MoneyProvider() {

    var locale;

    // Function called by the config to set up the provider
    this.setLocale = function(value) {
        locale = value;   
    };

    // All providers need to implement a $get method which returns
    // an instance of the custom class which constitutes the service
    this.$get = function moneyFactory() {
        return new Money(locale);
    };
});

// We can configure a PROVIDER on application initialisation.
app.config(['moneyProvider', function(moneyProvider) {
    moneyProvider.setLocale('uk');
    //moneyProvider.setLocale('eu'); 
}]);

// The ubiquitous controller
app.controller('mainCtrl', function($scope, title, strapline, random, money) {

    // Plain old VALUE(s)
    this.title = title;
    this.strapline = strapline;

    this.count = 0;

    // Compute values using our money provider    
    this.earn = money.convertValue(random); // random is computed @ runtime
    this.earned = money.convertValue(0);

    this.handleClick = function() { 
        this.count ++;
        this.earned = money.convertValue(random * this.count);
    };
});

demo trabalho .





angularjs-provider