Lo $scope
que ves que se inyecta en los controladores no es un servicio (como el resto de las cosas inyectables), sino un objeto Scope. Se pueden crear muchos objetos de alcance (generalmente heredando prototípicamente de un alcance principal). La raíz de todos los ámbitos es $rootScope
y puede crear un nuevo ámbito secundario utilizando el $new()
método de cualquier ámbito (incluido $rootScope
).
El propósito de un alcance es "unir" la presentación y la lógica empresarial de su aplicación. No tiene mucho sentido $scope
convertir un en un servicio.
Los servicios son objetos singleton que se utilizan (entre otras cosas) para compartir datos (por ejemplo, entre varios controladores) y generalmente encapsulan piezas de código reutilizables (ya que pueden inyectarse y ofrecer sus "servicios" en cualquier parte de su aplicación que los necesite: controladores, directivas, filtros, otros servicios, etc.).
Estoy seguro de que varios enfoques funcionarían para usted. Una es la siguiente:
dado que StudentService
está a cargo de manejar los datos de los estudiantes, puede StudentService
mantener una matriz de estudiantes y dejar que la "comparta" con quien pueda estar interesado (por ejemplo, su $scope
). Esto tiene aún más sentido, si hay otras vistas / controladores / filtros / servicios que necesitan tener acceso a esa información (si no hay ninguna en este momento, no se sorprenda si comienzan a aparecer pronto).
Cada vez que se agrega un nuevo estudiante (usando el save()
método del servicio ), la propia matriz de estudiantes del servicio se actualizará y todos los demás objetos que compartan esa matriz también se actualizarán automáticamente.
Según el enfoque descrito anteriormente, su código podría verse así:
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.
});
};
}
]);
Una cosa con la que debe tener cuidado al usar este enfoque es nunca reasignar la matriz del servicio, porque entonces cualquier otro componente (por ejemplo, ámbitos) seguirá haciendo referencia a la matriz original y su aplicación se romperá.
Por ejemplo, para borrar la matriz en StudentService
:
/* DON'T DO THAT */
var clear = function () { students = []; }
/* DO THIS INSTEAD */
var clear = function () { students.splice(0, students.length); }
Vea también esta breve demostración .
PEQUEÑA ACTUALIZACIÓN:
Unas palabras para evitar la confusión que pueda surgir al hablar de utilizar un servicio, pero no de crearlo con la service()
función.
Citando los documentos en$provide
:
Un servicio angular es un objeto único creado por una fábrica de servicios . Estas fábricas de servicios son funciones que, a su vez, son creadas por un proveedor de servicios . Los proveedores de servicios son funciones de constructor. Cuando se crean instancias, deben contener una propiedad llamada $get
, que contiene la función de fábrica de servicios .
[...]
... el $provide
servicio tiene métodos auxiliares adicionales para registrar servicios sin especificar un proveedor:
- proveedor (proveedor) : registra un proveedor de servicios con $ injector
- constante (obj) : registra un valor / objeto al que pueden acceder los proveedores y servicios.
- valor (obj) : registra un valor / objeto al que solo pueden acceder los servicios, no los proveedores.
- factory (fn) : registra una función de fábrica de servicios, fn, que se incluirá en un objeto de proveedor de servicios, cuya propiedad $ get contendrá la función de fábrica dada.
- service (class) : registra una función de constructor, clase que se incluirá en un objeto de proveedor de servicios, cuya propiedad $ get instanciará un nuevo objeto utilizando la función de constructor dada.
Básicamente, lo que dice es que todos los servicios de Angular se registran usando $provide.provider()
, pero hay métodos de "atajos" para servicios más simples (dos de los cuales son service()
y factory()
).
Todo "se reduce" a un servicio, por lo que no importa mucho el método que utilice (siempre que los requisitos de su servicio puedan ser cubiertos por ese método).
Por cierto, provider
vs service
vs factory
es uno de los conceptos más confusos para los recién llegados de Angular, pero afortunadamente hay muchos recursos (aquí en SO) para facilitar las cosas. (Solo busca alrededor).
(Espero que eso lo aclare, avíseme si no es así).