Le $scope
que vous voyez être injecté dans les contrôleurs n'est pas un service (comme le reste des éléments injectables), mais un objet Scope. De nombreux objets d'étendue peuvent être créés (généralement en héritant de manière prototypique d'une étendue parent). La racine de toutes les étendues est le $rootScope
et vous pouvez créer une nouvelle étendue enfant en utilisant la $new()
méthode de n'importe quelle étendue (y compris la $rootScope
).
Le but d'un Scope est de «coller» la présentation et la logique métier de votre application. Cela n'a pas beaucoup de sens de $scope
transformer un en service.
Les services sont des objets uniques utilisés (entre autres) pour partager des données (par exemple entre plusieurs contrôleurs) et encapsulent généralement des morceaux de code réutilisables (puisqu'ils peuvent être injectés et offrir leurs «services» dans n'importe quelle partie de votre application qui en a besoin: contrôleurs, directives, filtres, autres services, etc.).
Je suis sûr que diverses approches fonctionneraient pour vous. L'une d'entre elles est la suivante: étant
donné que le StudentService
est chargé de traiter les données des étudiants, vous pouvez avoir le StudentService
garder un tableau d'étudiants et le laisser "partager" avec qui pourrait être intéressé (par exemple votre $scope
). Cela a encore plus de sens, s'il y a d'autres vues / contrôleurs / filtres / services qui doivent avoir accès à ces informations (s'il n'y en a pas pour le moment, ne soyez pas surpris si elles commencent à apparaître bientôt).
Chaque fois qu'un nouvel étudiant est ajouté (en utilisant la save()
méthode du service ), le propre tableau d'étudiants du service sera mis à jour et tous les autres objets partageant ce tableau seront également mis à jour automatiquement.
Basé sur l'approche décrite ci-dessus, votre code pourrait ressembler à ceci:
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.
});
};
}
]);
Une chose à laquelle vous devez faire attention lorsque vous utilisez cette approche est de ne jamais réaffecter le tableau du service, car alors tous les autres composants (par exemple les étendues) référenceront toujours le tableau d'origine et votre application se cassera.
Par exemple, pour effacer le tableau dans StudentService
:
/* DON'T DO THAT */
var clear = function () { students = []; }
/* DO THIS INSTEAD */
var clear = function () { students.splice(0, students.length); }
Voir aussi cette courte démo .
PETITE MISE À JOUR:
Quelques mots pour éviter la confusion qui peut survenir en parlant d'utiliser un service, mais pas de le créer avec la service()
fonction
Citant les documents sur$provide
:
Un angulaire service est un objet singleton créé par une fabrique de services . Ces usines de services sont des fonctions qui, à leur tour, sont créées par un fournisseur de services . Les fournisseurs de services sont des fonctions de constructeur. Lorsqu'elles sont instanciées, elles doivent contenir une propriété appelée $get
, qui contient la fonction de fabrique de service .
[...]
... le $provide
service dispose de méthodes d'assistance supplémentaires pour enregistrer les services sans spécifier de fournisseur:
- provider (provider) - enregistre un fournisseur de services avec l'injecteur $
- constant (obj) - enregistre une valeur / un objet auquel les fournisseurs et les services peuvent accéder.
- value (obj) - enregistre une valeur / un objet qui n'est accessible que par les services, pas par les fournisseurs.
- factory (fn) - enregistre une fonction de fabrique de service, fn, qui sera encapsulée dans un objet fournisseur de services, dont la propriété $ get contiendra la fonction de fabrique donnée.
- service (class) - enregistre une fonction constructeur, classe qui sera encapsulée dans un objet fournisseur de services, dont la propriété $ get instanciera un nouvel objet en utilisant la fonction constructeur donnée.
Fondamentalement, ce qu'il dit, c'est que chaque service Angular est enregistré en utilisant $provide.provider()
, mais il existe des méthodes de «raccourci» pour des services plus simples (dont deux sont service()
et factory()
).
Tout se résume à un service, donc peu importe la méthode que vous utilisez (tant que les exigences de votre service peuvent être couvertes par cette méthode).
BTW, provider
vs service
vs factory
est l'un des concepts les plus déroutants pour les nouveaux arrivants angulaires, mais heureusement, il existe de nombreuses ressources (ici sur SO) pour faciliter les choses. (Il suffit de chercher.)
(J'espère que cela clarifie les choses - faites-moi savoir si ce n'est pas le cas.)