Те, $scope
що ви бачите, що його вводять у контролери, - це не якась послуга (як, наприклад, решта ін'єкційних матеріалів), а об'єкт Scope. Можна створити багато об'єктів сфери застосування (як правило, прототипічно успадковуються від батьківського діапазону). Корінь усіх областей - це те, $rootScope
і ви можете створити нове дочірнє поле, використовуючи $new()
метод будь-якої області (включаючи $rootScope
).
Мета Області - "склеїти" презентацію та ділову логіку вашого додатка. Немає особливого сенсу передавати $scope
послугу.
Служби - це одноособові об'єкти, які використовуються (серед іншого) для обміну даними (наприклад, між кількома контролерами) і, як правило, інкапсулюють багаторазові фрагменти коду (оскільки їх можна вводити та пропонувати свої "послуги" в будь-якій частині вашої програми, яка їм потрібна: контролери, директиви, фільтри, інші послуги тощо).
Впевнений, для вас підійдуть різні підходи. Одне таке:
Оскільки StudentService
це відповідає за обробку даних студентів, ви можете мати StudentService
набір студентів та дозволити їм "поділитися" ним із тим, хто може зацікавити (наприклад, вашим $scope
). Це має ще більший сенс, якщо є інші види / контролери / фільтри / служби, яким потрібно мати доступ до цієї інформації (якщо зараз таких немає, не дивуйтеся, якщо вони незабаром почнуть вискакувати).
Кожного разу, коли додається новий студент (використовуючи save()
метод сервісу ), власний масив учнів служби буде оновлюватися, і кожен інший об'єкт, що обмінюється цим масивом, також автоматично оновлюється.
Виходячи з описаного вище підходу, ваш код може виглядати так:
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.
});
};
}
]);
Одне, з чим слід бути обережним при використанні цього підходу, - це ніколи не призначати масив служби, оскільки тоді будь-які інші компоненти (наприклад, сфери дії) все ще будуть посилатися на початковий масив, і ваш додаток зламається.
Наприклад, щоб очистити масив у StudentService
:
/* DON'T DO THAT */
var clear = function () { students = []; }
/* DO THIS INSTEAD */
var clear = function () { students.splice(0, students.length); }
Дивіться також цю коротку демонстрацію .
МАЛКО ОНОВЛЕННЯ:
Кілька слів, щоб уникнути плутанини, яка може виникнути під час розмови про використання послуги, але не створювати її за допомогою service()
функції.
Цитуючи документи на$provide
:
Кутова служба - це однотонний об'єкт, створений фабрикою обслуговування . Ці фабрики послуг - це функції, які, у свою чергу, створюються постачальником послуг . В сервіс - провайдери є функціями конструктора. При екземплярі вони повинні містити властивість $get
, що називається , яка виконує функцію фабричного обслуговування .
[...]
... $provide
сервіс має додаткові допоміжні методи для реєстрації послуг без вказівки постачальника:
- провайдер (провайдер) - реєструє постачальника послуг за допомогою інжектора $
- константа (obj) - реєструє значення / об'єкт, до якого можуть отримати доступ провайдери та послуги.
- value (obj) - реєструє значення / об'єкт, доступ до якого можуть отримати лише сервіси, а не провайдери.
- factory (fn) - реєструє функцію фабрики послуг, fn, яка буде обгорнута об'єктом постачальника послуг, властивість якого $ get буде містити задану функцію заводу.
- service (class) - реєструє функцію конструктора, клас, який буде загорнутий у об’єкт постачальника послуг, властивість $ get якого інстанціює новий об'єкт за допомогою заданої функції конструктора.
В основному, це говорить про те, що кожна послуга Angular реєструється за допомогою $provide.provider()
, але існують методи "швидкого доступу" для більш простих сервісів (два з яких є service()
і factory()
).
Це все "зводиться" до послуги, тому це не має великої різниці, який метод ви використовуєте (до тих пір, поки вимоги до вашої послуги можуть бути покриті цим методом).
BTW, provider
vs service
vs factory
є однією з найбільш заплутаних концепцій для кутових новачків, але, на щастя, існує маса ресурсів (тут на SO), щоб полегшити справи. (Просто пошукайте навколо.)
(Я сподіваюся, що це очистить - дайте мені знати, якщо це не так.)