O $scope
que você vê sendo injetado nos controladores não é um serviço (como o resto das coisas injetáveis), mas é um objeto Scope. Muitos objetos de escopo podem ser criados (geralmente herdando prototipicamente de um escopo pai). A raiz de todos os escopos é o $rootScope
e você pode criar um novo escopo filho usando o $new()
método de qualquer escopo (incluindo o $rootScope
).
O objetivo de um Escopo é "unir" a apresentação e a lógica de negócios de seu aplicativo. Não faz muito sentido passar um $scope
para um serviço.
Serviços são objetos singleton usados (entre outras coisas) para compartilhar dados (por exemplo, entre vários controladores) e geralmente encapsulam pedaços de código reutilizáveis (uma vez que podem ser injetados e oferecer seus "serviços" em qualquer parte de seu aplicativo que precise deles: controladores, diretivas, filtros, outros serviços, etc.).
Tenho certeza de que várias abordagens funcionariam para você. Uma é a seguinte:
como o StudentService
é responsável por lidar com os dados dos alunos, você pode StudentService
manter uma matriz de alunos e deixá-la "compartilhá-la" com quem estiver interessado (por exemplo, o seu $scope
). Isso faz ainda mais sentido, se houver outras visualizações / controladores / filtros / serviços que precisam ter acesso a essas informações (se não houver nenhuma agora, não se surpreenda se elas começarem a aparecer logo).
Cada vez que um novo aluno é adicionado (usando o save()
método do serviço ), a própria matriz de alunos do serviço será atualizada e todos os outros compartilhamentos de objetos dessa matriz também serão atualizados automaticamente.
Com base na abordagem descrita acima, seu código pode ser assim:
angular.
module('cfd', []).
factory('StudentService', ['$http', '$q', function ($http, $q) {
var path = 'data/people/students.json';
var students = [];
// In the real app, instead of just updating the students array
// (which will be probably already done from the controller)
// this method should send the student data to the server and
// wait for a response.
// This method returns a promise to emulate what would happen
// when actually communicating with the server.
var save = function (student) {
if (student.id === null) {
students.push(student);
} else {
for (var i = 0; i < students.length; i++) {
if (students[i].id === student.id) {
students[i] = student;
break;
}
}
}
return $q.resolve(student);
};
// Populate the students array with students from the server.
$http.get(path).then(function (response) {
response.data.forEach(function (student) {
students.push(student);
});
});
return {
students: students,
save: save
};
}]).
controller('someCtrl', ['$scope', 'StudentService',
function ($scope, StudentService) {
$scope.students = StudentService.students;
$scope.saveStudent = function (student) {
// Do some $scope-specific stuff...
// Do the actual saving using the StudentService.
// Once the operation is completed, the $scope's `students`
// array will be automatically updated, since it references
// the StudentService's `students` array.
StudentService.save(student).then(function () {
// Do some more $scope-specific stuff,
// e.g. show a notification.
}, function (err) {
// Handle the error.
});
};
}
]);
Uma coisa que você deve ter cuidado ao usar essa abordagem é nunca reatribuir o array do serviço, porque então quaisquer outros componentes (por exemplo, escopos) ainda farão referência ao array original e seu aplicativo será interrompido.
Por exemplo, para limpar a matriz em StudentService
:
/* DON'T DO THAT */
var clear = function () { students = []; }
/* DO THIS INSTEAD */
var clear = function () { students.splice(0, students.length); }
Veja, também, esta pequena demonstração .
LITTLE UPDATE:
Algumas palavras para evitar a confusão que pode surgir ao falar sobre o uso de um serviço, mas não criá-lo com a service()
função.
Citando os documentos em$provide
:
Um serviço Angular é um objeto singleton criado por uma fábrica de serviços . Essas fábricas de serviços são funções que, por sua vez, são criadas por um provedor de serviços . Os provedores de serviços são funções construtoras. Quando instanciados, eles devem conter uma propriedade chamada $get
, que contém a função de fábrica de serviço .
[...]
... o $provide
serviço tem métodos auxiliares adicionais para registrar serviços sem especificar um provedor:
- provedor (provedor) - registra um provedor de serviços com o $ injetor
- constante (obj) - registra um valor / objeto que pode ser acessado por provedores e serviços.
- valor (obj) - registra um valor / objeto que só pode ser acessado por serviços, não por provedores.
- factory (fn) - registra uma função de fábrica de serviço, fn, que será empacotada em um objeto de provedor de serviço, cuja propriedade $ get conterá a função de fábrica fornecida.
- serviço (classe) - registra uma função construtora, classe que será envolvida em um objeto de provedor de serviço, cuja propriedade $ get instanciará um novo objeto usando a função construtora fornecida.
Basicamente, o que ele diz é que todo serviço Angular é registrado usando $provide.provider()
, mas existem métodos de "atalho" para serviços mais simples (dois dos quais são service()
e factory()
).
Tudo se resume a um serviço, então não faz muita diferença o método que você usa (contanto que os requisitos para seu serviço possam ser cobertos por esse método).
BTW, provider
vs service
vs factory
é um dos conceitos mais confusos para os novatos do Angular, mas felizmente existem muitos recursos (aqui no SO) para tornar as coisas mais fáceis. (Basta pesquisar.)
(Espero que isso esclareça - me avise se não resolver).