Das $scope
, was Sie sehen, wie es in Controller injiziert wird, ist kein Dienst (wie der Rest des injizierbaren Materials), sondern ein Scope-Objekt. Es können viele Bereichsobjekte erstellt werden (normalerweise prototypisch von einem übergeordneten Bereich erben). Die Wurzel aller Bereiche ist der, $rootScope
und Sie können einen neuen untergeordneten Bereich mit der $new()
Methode eines beliebigen Bereichs (einschließlich des $rootScope
) erstellen .
Der Zweck eines Bereichs besteht darin, die Präsentation und die Geschäftslogik Ihrer App "zusammenzukleben". Es macht nicht viel Sinn, a zu bestehen$scope
an einen Dienst .
Services sind Singleton-Objekte, die (unter anderem) zum Teilen von Daten (z. B. zwischen mehreren Controllern) verwendet werden und im Allgemeinen wiederverwendbare Codeteile kapseln (da sie injiziert werden können und ihre "Services" in jedem Teil Ihrer App anbieten, der sie benötigt: Controller, Richtlinien, Filter, andere Dienste usw.).
Ich bin sicher, dass verschiedene Ansätze für Sie funktionieren würden. Eines ist das Folgende:
Da das StudentService
für den Umgang mit Studentendaten zuständig ist, können Sie StudentService
eine Reihe von Studenten behalten und es mit jedem "teilen" lassen, der interessiert sein könnte (z $scope
. B. Ihrem ). Dies ist umso sinnvoller, wenn andere Ansichten / Controller / Filter / Dienste Zugriff auf diese Informationen benötigen (wenn derzeit keine verfügbar sind, wundern Sie sich nicht, wenn sie bald auftauchen).
Jedes Mal, wenn ein neuer Schüler hinzugefügt wird (unter Verwendung der save()
Dienstmethode), wird das eigene Schülerarray des Dienstes aktualisiert, und jedes andere Objekt, das dieses Array gemeinsam nutzt , wird ebenfalls automatisch aktualisiert.
Basierend auf dem oben beschriebenen Ansatz könnte Ihr Code folgendermaßen aussehen:
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.
});
};
}
]);
Eine Sache, bei der Sie bei diesem Ansatz vorsichtig sein sollten, ist, das Array des Dienstes niemals neu zuzuweisen, da dann alle anderen Komponenten (z. B. Bereiche) weiterhin auf das ursprüngliche Array verweisen und Ihre App beschädigt wird.
ZB um das Array zu löschen in StudentService
:
/* DON'T DO THAT */
var clear = function () { students = []; }
/* DO THIS INSTEAD */
var clear = function () { students.splice(0, students.length); }
Siehe auch diese kurze Demo .
KLEINES UPDATE:
Ein paar Worte, um die Verwirrung zu vermeiden, die auftreten kann, wenn über die Verwendung eines Dienstes gesprochen wird, dieser jedoch nicht mit der service()
Funktion erstellt wird.
Zitieren der Dokumente auf$provide
:
Ein Angular- Service ist ein Singleton-Objekt, das von einer Service-Factory erstellt wurde . Diese Servicefabriken sind Funktionen, die wiederum von einem Service Provider erstellt werden . Die Dienstleister sind Konstruktorfunktionen. Wenn sie instanziiert werden, müssen sie eine aufgerufene Eigenschaft enthalten $get
, die die Service Factory- Funktion enthält.
[...]
... der $provide
Dienst verfügt über zusätzliche Hilfsmethoden zum Registrieren von Diensten ohne Angabe eines Anbieters:
- Provider (Provider) - registriert einen Service Provider beim $ Injector
- Konstante (obj) - registriert einen Wert / ein Objekt, auf das bzw. das Anbieter und Dienste zugreifen können.
- Wert (obj) - registriert einen Wert / ein Objekt, auf das nur von Diensten zugegriffen werden kann, nicht von Anbietern.
- Fabrik (fn) - registriert eine Service-Factory-Funktion, fn, die in ein Service-Provider-Objekt eingeschlossen wird, dessen $ get-Eigenschaft die angegebene Factory-Funktion enthält.
- service (class) - registriert eine Konstruktorfunktion, eine Klasse, die in ein Service Provider-Objekt eingeschlossen wird, dessen $ get-Eigenschaft ein neues Objekt mithilfe der angegebenen Konstruktorfunktion instanziiert.
Grundsätzlich heißt es, dass jeder Angular-Dienst mit registriert wird $provide.provider()
, es gibt jedoch Verknüpfungsmethoden für einfachere Dienste (zwei davon sind service()
und factory()
).
Alles läuft auf einen Service hinaus, sodass es keinen großen Unterschied macht, welche Methode Sie verwenden (solange die Anforderungen für Ihren Service durch diese Methode abgedeckt werden können).
Übrigens provider
vs service
vs.factory
ist eines der verwirrendsten Konzepte für Angular-Neulinge, aber zum Glück gibt es viele Ressourcen (hier auf SO), um die Dinge einfacher zu machen. (Suchen Sie einfach herum.)
(Ich hoffe, das klärt es auf - lass es mich wissen, wenn es nicht so ist.)