To $scope
, co widzisz, jest wstrzykiwane do kontrolerów, nie jest jakąś usługą (jak reszta rzeczy do wstrzykiwania), ale jest obiektem Scope. Można utworzyć wiele obiektów zakresu (zwykle prototypowo dziedzicząc z zakresu nadrzędnego). Podstawą wszystkich zakresów jest $rootScope
i można utworzyć nowy zakres podrzędny przy użyciu $new()
metody dowolnego zakresu (w tym $rootScope
).
Celem zakresu jest „sklejenie” prezentacji i logiki biznesowej aplikacji. Przekazywanie a $scope
do usługi nie ma większego sensu .
Usługi to pojedyncze obiekty używane (między innymi) do udostępniania danych (np. Między kilkoma kontrolerami) i generalnie hermetyzowania fragmentów kodu wielokrotnego użytku (ponieważ można je wstrzykiwać i oferować swoje „usługi” w dowolnej części aplikacji, która ich potrzebuje: kontrolery, dyrektywy, filtry, inne usługi itp.).
Jestem pewien, że sprawdzą się u Ciebie różne podejścia. Jedna z nich jest następująca:
ponieważ StudentService
jest odpowiedzialny za przetwarzanie danych uczniów, możesz StudentService
przechowywać ich tablicę i „dzielić się” nimi z każdym, kto może być zainteresowany (np. Twoim $scope
). Ma to jeszcze większy sens, jeśli istnieją inne widoki / kontrolery / filtry / usługi, które muszą mieć dostęp do tych informacji (jeśli nie ma ich teraz, nie zdziw się, jeśli zaczną się pojawiać wkrótce).
Za każdym razem, gdy dodawany jest nowy uczeń (przy użyciu metody usługi save()
), własna tablica uczniów usługi będzie aktualizowana, a każdy inny obiekt udostępniający tę tablicę również zostanie automatycznie zaktualizowany.
Bazując na podejściu opisanym powyżej, Twój kod mógłby wyglądać następująco:
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.
});
};
}
]);
Jedną rzeczą, na którą należy zachować ostrożność podczas korzystania z tego podejścia, jest to, aby nigdy nie ponownie przypisywać tablicy usługi, ponieważ wtedy wszelkie inne komponenty (np. Zakresy) będą nadal odwoływać się do oryginalnej tablicy, a aplikacja ulegnie awarii.
Np., Aby wyczyścić tablicę w StudentService
:
/* DON'T DO THAT */
var clear = function () { students = []; }
/* DO THIS INSTEAD */
var clear = function () { students.splice(0, students.length); }
Zobacz także to krótkie demo .
MAŁA AKTUALIZACJA:
Kilka słów, aby uniknąć nieporozumień, które mogą powstać podczas mówienia o korzystaniu z usługi, ale nie podczas tworzenia jej za pomocą service()
funkcji.
Cytując dokumenty na$provide
:
Kątowym usługa jest pojedyncza obiekt stworzony przez fabrykę usług . Te fabryki usług to funkcje, które z kolei są tworzone przez usługodawcę . Do usługodawcy są funkcje konstruktora. Po utworzeniu muszą zawierać właściwość nazwaną $get
, która przechowuje funkcję fabryki usług .
[...]
... $provide
usługa posiada dodatkowe pomocnicze metody rejestracji usług bez określania dostawcy:
- provider (provider) - rejestruje usługodawcę w $ injectorze
- stała (obj) - rejestruje wartość / obiekt, do którego mają dostęp dostawcy i usługi.
- wartość (obj) - rejestruje wartość / obiekt, do którego dostęp mają tylko usługi, a nie dostawcy.
- factory (fn) - rejestruje funkcję fabryki usług, fn, która zostanie opakowana w obiekt dostawcy usług, którego właściwość $ get będzie zawierać daną funkcję fabryki.
- service (class) - rejestruje funkcję konstruktora, klasę, która zostanie opakowana w obiekt dostawcy usług, której właściwość $ get utworzy instancję nowego obiektu przy użyciu podanej funkcji konstruktora.
Zasadniczo mówi się, że każda usługa Angular jest rejestrowana przy użyciu $provide.provider()
, ale istnieją metody „skrótów” dla prostszych usług (z których dwie to service()
i factory()
).
To wszystko „sprowadza się” do usługi, więc nie ma większego znaczenia, której metody użyjesz (o ile wymagania dotyczące Twojej usługi mogą być objęte tą metodą).
BTW, provider
vs service
vs factory
to jedna z najbardziej zagmatwanych koncepcji dla nowicjuszy Angulara, ale na szczęście istnieje wiele zasobów (tutaj na SO), które ułatwiają życie. (Po prostu poszukaj.)
(Mam nadzieję, że to wyjaśnia sprawę - daj mi znać, jeśli nie.)