Em vez disso, basta preencher a tabela com "sim" e "não" sem explicação, irei detalhar um pouco mais.
[Nota, adicionada após o término: isso acabou sendo ... um pouco mais longo do que eu esperava. Há um tl; dr na parte inferior, mas espero que isso seja informativo.]
[Esta resposta também foi adicionada ao wiki do AngularJS: Entendendo a injeção de dependência ]
O $provide
serviço é responsável por informar à Angular como criar novas coisas injetáveis; essas coisas são chamadas de serviços . Os serviços são definidos por coisas chamadas provedores , que é o que você cria quando usa $provide
. A definição de um provedor é feita pelo provider
método no $provide
serviço, e você pode se apossar do $provide
serviço solicitando que ele seja injetado na config
função de um aplicativo . Um exemplo pode ser algo como isto:
app.config(function($provide) {
$provide.provider('greeting', function() {
this.$get = function() {
return function(name) {
alert("Hello, " + name);
};
};
});
});
Aqui nós definimos um novo provedor para um serviço chamado greeting
; podemos injetar uma variável nomeada greeting
em qualquer função injetável (como controladores, mais sobre isso posteriormente) e o Angular chamará a $get
função do provedor para retornar uma nova instância do serviço. Nesse caso, o que será injetado é uma função que recebe um name
parâmetro e uma alert
mensagem com base no nome. Podemos usá-lo assim:
app.controller('MainController', function($scope, greeting) {
$scope.onClick = function() {
greeting('Ford Prefect');
};
});
Agora, aqui está o truque. factory
,, service
e value
todos são apenas atalhos para definir várias partes de um provedor - ou seja, eles fornecem um meio de definir um provedor sem precisar digitar tudo isso. Por exemplo, você pode escrever exatamente o mesmo provedor da seguinte maneira:
app.config(function($provide) {
$provide.factory('greeting', function() {
return function(name) {
alert("Hello, " + name);
};
});
});
É importante entender, então vou reformular: sob o capô, o AngularJS está chamando exatamente o mesmo código que escrevemos acima (a $provide.provider
versão) para nós. Não há, literalmente, 100% de diferença nas duas versões. value
funciona da mesma maneira - se o que quer que retornássemos da nossa $get
função (também conhecida como nossa factory
função) é sempre exatamente o mesmo, podemos escrever ainda menos código usando value
. Por exemplo, como sempre retornamos a mesma função para nosso greeting
serviço, também podemos value
defini-la:
app.config(function($provide) {
$provide.value('greeting', function(name) {
alert("Hello, " + name);
});
});
Novamente, isso é 100% idêntico aos outros dois métodos que usamos para definir essa função - é apenas uma maneira de salvar algumas digitações.
Agora você provavelmente notou essa app.config(function($provide) { ... })
coisa chata que tenho usado. Como definir novos provedores (através de qualquer um dos métodos acima) é tão comum, o AngularJS expõe os $provider
métodos diretamente no objeto do módulo, para economizar ainda mais digitação:
var myMod = angular.module('myModule', []);
myMod.provider("greeting", ...);
myMod.factory("greeting", ...);
myMod.value("greeting", ...);
Todos eles fazem o mesmo que as app.config(...)
versões mais detalhadas que usamos anteriormente.
O injetável que pulei até agora é constant
. Por enquanto, é fácil dizer que funciona da mesma maneira value
. Veremos que há uma diferença mais tarde.
Para revisar , todos esses trechos de código estão fazendo exatamente a mesma coisa:
myMod.provider('greeting', function() {
this.$get = function() {
return function(name) {
alert("Hello, " + name);
};
};
});
myMod.factory('greeting', function() {
return function(name) {
alert("Hello, " + name);
};
});
myMod.value('greeting', function(name) {
alert("Hello, " + name);
});
O injetor é responsável por realmente criar instâncias de nossos serviços usando o código que fornecemos via $provide
(sem trocadilhos). Sempre que você escreve uma função que recebe argumentos injetados, vê o injetor funcionando. Cada aplicativo AngularJS possui um $injector
que é criado quando o aplicativo é iniciado pela primeira vez; você pode controlá-lo injetando $injector
qualquer função injetável (sim, $injector
sabe como se injetar!)
Depois de ter $injector
, você pode obter uma instância de um serviço definido chamando get
-o com o nome do serviço. Por exemplo,
var greeting = $injector.get('greeting');
greeting('Ford Prefect');
O injetor também é responsável por injetar serviços nas funções; por exemplo, você pode injetar serviços magicamente em qualquer função que tenha usando o invoke
método do injetor ;
var myFunction = function(greeting) {
greeting('Ford Prefect');
};
$injector.invoke(myFunction);
Vale a pena notar que o injetor criará apenas uma instância de um serviço uma vez . Em seguida, ele armazena em cache o que o provedor retornar pelo nome do serviço; Na próxima vez em que você solicitar o serviço, você obterá exatamente o mesmo objeto.
Portanto, para responder sua pergunta, você pode injetar serviços em qualquer função chamada$injector.invoke
. Isso inclui
- funções de definição do controlador
- funções de definição de diretiva
- funções de definição de filtro
- os
$get
métodos dos provedores (também conhecidos como factory
funções de definição)
Como constant
s e value
s sempre retornam um valor estático, eles não são invocados pelo injetor e, portanto, você não pode injetá-los com nada.
Configurando Provedores
Você pode estar se perguntando por que alguém iria incomodar a criação de um provedor de pleno direito com o provide
método se factory
, value
, etc, são muito mais fácil. A resposta é que os provedores permitem muita configuração. Já mencionamos que, ao criar um serviço por meio do provedor (ou qualquer um dos atalhos fornecidos pelo Angular), você cria um novo provedor que define como esse serviço é construído. O que eu não mencionei é que esses provedores podem ser injetados emconfig
seções do seu aplicativo para que você possa interagir com eles!
Primeiro, o Angular executa seu aplicativo em duas fases - as fases config
e run
. A config
fase, como vimos, é onde você pode configurar qualquer provedor, conforme necessário. É também aqui que diretivas, controladores, filtros e similares são configurados. A run
fase, como você pode imaginar, é onde o Angular realmente compila seu DOM e inicia seu aplicativo.
Você pode adicionar código adicional a ser executado nessas fases com as funções myMod.config
e myMod.run
- cada uma delas executa uma função para executar durante essa fase específica. Como vimos na primeira seção, essas funções são injetáveis - injetamos o $provide
serviço interno em nosso primeiro exemplo de código. No entanto, o que vale a pena notar é que, durante a config
fase, apenas os provedores podem ser injetados (com exceção dos serviços no AUTO
módulo-- $provide
e $injector
).
Por exemplo, o seguinte não é permitido :
myMod.config(function(greeting) {
// WON'T WORK -- greeting is an *instance* of a service.
// Only providers for services can be injected in config blocks.
});
O que você faz tem acesso a quaisquer provedores de serviços que você fez:
myMod.config(function(greetingProvider) {
// a-ok!
});
Há uma exceção importante: constant
s, uma vez que não podem ser alterados, podem ser injetados dentro de config
blocos (é assim que diferem de value
s). Eles são acessados apenas pelo nome (não é Provider
necessário sufixo).
Sempre que você define um provedor para um serviço, esse provedor é nomeado serviceProvider
, onde service
é o nome do serviço. Agora podemos usar o poder dos provedores para fazer coisas mais complicadas!
myMod.provider('greeting', function() {
var text = 'Hello, ';
this.setText = function(value) {
text = value;
};
this.$get = function() {
return function(name) {
alert(text + name);
};
};
});
myMod.config(function(greetingProvider) {
greetingProvider.setText("Howdy there, ");
});
myMod.run(function(greeting) {
greeting('Ford Prefect');
});
Agora, temos uma função em nosso provedor chamada setText
que podemos usar para personalizar nossa alert
; podemos obter acesso a esse provedor em um config
bloco para chamar esse método e personalizar o serviço. Quando finalmente executamos nosso aplicativo, podemos pegar o greeting
serviço e testá-lo para ver se nossa personalização entrou em vigor.
Como este é um exemplo mais complexo, aqui está uma demonstração de trabalho: http://jsfiddle.net/BinaryMuse/9GjYg/
As funções do controlador podem ser injetadas, mas os próprios controladores não podem ser injetados em outras coisas. Isso ocorre porque os controladores não são criados por meio do provedor. Em vez disso, existe um serviço Angular interno chamado $controller
responsável pela configuração de seus controladores. Quando você liga myMod.controller(...)
, está realmente acessando o provedor deste serviço , assim como na última seção.
Por exemplo, quando você define um controlador como este:
myMod.controller('MainController', function($scope) {
// ...
});
O que você está realmente fazendo é o seguinte:
myMod.config(function($controllerProvider) {
$controllerProvider.register('MainController', function($scope) {
// ...
});
});
Posteriormente, quando o Angular precisar criar uma instância do seu controlador, ele usará o $controller
serviço (que por sua vez usa o $injector
para chamar a função do controlador para que também seja injetada suas dependências).
Filtros e Diretivas
filter
e directive
funciona exatamente da mesma maneira que controller
; filter
usa um serviço chamado $filter
e seu provedor $filterProvider
, enquanto directive
usa um serviço chamado $compile
e seu provedor $compileProvider
. Alguns links:
Conforme os outros exemplos, myMod.filter
e myMod.directive
são atalhos para configurar esses serviços.
Portanto, para resumir, qualquer função que seja chamada $injector.invoke
pode ser injetada . Isso inclui, no seu gráfico (mas não se limita a):
- controlador
- diretiva
- fábrica
- filtro
- provedor
$get
(ao definir provedor como um objeto)
- função de provedor (ao definir provedor como uma função de construtor)
- serviço
O provedor cria novos serviços que podem ser injetados nas coisas . Isso inclui:
- constante
- fábrica
- fornecedor
- serviço
- valor
Dito isto, serviços internos gostam $controller
e $filter
podem ser injetados, e você pode usá- los para se apossar dos novos filtros e controladores que você definiu com esses métodos (mesmo que as coisas que você definiu não possam, por si só, ser injetado nas coisas).
Para além de que, qualquer função invocada-injector pode ser injectado com qualquer serviço fornecido pelo provedor - não há nenhuma restrição (excepto o config
e run
diferenças aqui listados).