То, $scope
что вы видите, внедряемое в контроллеры, не является какой-то службой (как и остальная часть вводимого материала), а является объектом Scope. Могут быть созданы многие объекты области видимости (обычно прототипически наследуемые от родительской области). Корнем всех областей видимости является область, $rootScope
и вы можете создать новую дочернюю область, используя $new()
метод любой области (включая $rootScope
).
Цель Scope - «склеить» презентацию и бизнес-логику вашего приложения. Нет смысла передавать a $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
:
Сервис Angular - это одноэлементный объект, созданный фабрикой сервисов . Эти сервисные фабрики представляют собой функции, которые, в свою очередь, создаются поставщиком услуг . В сервис - провайдеры являются функциями конструктора. При создании они должны содержать вызываемое свойство $get
, которое содержит функцию фабрики служб .
[...]
... у $provide
сервиса есть дополнительные вспомогательные методы для регистрации сервисов без указания провайдера:
- provider (поставщик) - регистрирует поставщика услуг с помощью инжектора $
- константа (obj) - регистрирует значение / объект, к которому могут получить доступ провайдеры и службы.
- value (obj) - регистрирует значение / объект, к которому могут получить доступ только службы, а не поставщики.
- factory (fn) - регистрирует функцию фабрики служб, fn, которая будет заключена в объект поставщика службы, чье свойство $ get будет содержать данную фабричную функцию.
- service (class) - регистрирует функцию-конструктор, класс, который будет заключен в объект поставщика услуг, чье свойство $ get будет создавать экземпляр нового объекта с использованием данной функции-конструктора.
По сути, это говорит о том, что каждая служба Angular регистрируется с использованием $provide.provider()
, но есть "ярлыки" для более простых служб (два из которых - service()
и factory()
).
Все «сводится» к сервису, поэтому не имеет большого значения, какой метод вы используете (если требования к вашему сервису могут быть удовлетворены этим методом).
Кстати, provider
vs service
vs factory
- одна из самых запутанных концепций для новичков в Angular, но, к счастью, есть много ресурсов (здесь, на SO), чтобы упростить задачу. (Просто поищите вокруг.)
(Надеюсь, это проясняет ситуацию - дайте мне знать, если это не так.)