Yang $scope
Anda lihat disuntikkan ke pengontrol bukanlah layanan (seperti bagian lain yang dapat diinjeksi), tetapi merupakan objek Scope. Banyak objek lingkup dapat dibuat (biasanya secara prototipikal mewarisi dari lingkup induk). Akar dari semua cakupan adalah $rootScope
dan Anda dapat membuat cakupan anak baru menggunakan $new()
metode cakupan apa pun (termasuk $rootScope
).
Tujuan dari Scope adalah untuk "merekatkan" presentasi dan logika bisnis aplikasi Anda. Tidak masuk akal untuk memasukkan a $scope
ke dalam sebuah layanan.
Layanan adalah objek tunggal yang digunakan (antara lain) untuk berbagi data (misalnya di antara beberapa pengontrol) dan umumnya merangkum potongan kode yang dapat digunakan kembali (karena mereka dapat dimasukkan dan menawarkan "layanan" mereka di bagian mana pun dari aplikasi Anda yang membutuhkannya: pengontrol, arahan, filter, layanan lain, dll.).
Saya yakin, berbagai pendekatan akan berhasil untuk Anda. Salah satunya adalah:
Karena StudentService
bertugas menangani data siswa, Anda dapat StudentService
menyimpan sejumlah siswa dan membiarkannya "membagikan" dengan siapa pun yang mungkin tertarik (misalnya Anda $scope
). Ini bahkan lebih masuk akal, jika ada tampilan / pengontrol / filter / layanan lain yang perlu memiliki akses ke info itu (jika tidak ada saat ini, jangan kaget jika mereka segera mulai bermunculan).
Setiap kali siswa baru ditambahkan (menggunakan metode layanan save()
), larik siswa layanan itu sendiri akan diperbarui dan setiap objek lain yang berbagi larik itu akan diperbarui secara otomatis juga.
Berdasarkan pendekatan yang dijelaskan di atas, kode Anda akan terlihat seperti ini:
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.
});
};
}
]);
Satu hal yang harus Anda perhatikan saat menggunakan pendekatan ini adalah jangan pernah menetapkan ulang larik layanan, karena komponen lain (misalnya cakupan) akan tetap merujuk ke larik asli dan aplikasi Anda akan rusak.
Misalnya untuk menghapus array di StudentService
:
/* DON'T DO THAT */
var clear = function () { students = []; }
/* DO THIS INSTEAD */
var clear = function () { students.splice(0, students.length); }
Lihat juga, demo singkat ini .
UPDATE KECIL:
Beberapa kata untuk menghindari kebingungan yang mungkin timbul saat berbicara tentang menggunakan layanan, tetapi tidak membuatnya dengan service()
fungsinya.
Mengutip dokumen tentang$provide
:
Sebuah sudut layanan adalah objek tunggal yang diciptakan oleh pabrik layanan . Pabrik layanan ini adalah fungsi yang, pada gilirannya, dibuat oleh penyedia layanan . The penyedia layanan adalah fungsi konstruktor. Ketika dibuat, mereka harus berisi properti yang dipanggil $get
, yang memegang fungsi pabrik layanan .
[...]
... $provide
layanan memiliki metode pembantu tambahan untuk mendaftarkan layanan tanpa menentukan penyedia:
- provider (provider) - mendaftarkan penyedia layanan dengan $ injector
- konstan (obj) - mendaftarkan nilai / objek yang dapat diakses oleh penyedia dan layanan.
- nilai (obj) - mendaftarkan nilai / objek yang hanya dapat diakses oleh layanan, bukan penyedia.
- factory (fn) - mendaftarkan fungsi pabrik layanan, fn, yang akan dibungkus dalam objek penyedia layanan, yang properti $ getnya akan berisi fungsi pabrik yang diberikan.
- service (class) - meregistrasikan fungsi konstruktor, kelas yang akan dibungkus dalam objek penyedia layanan, yang properti $ getnya akan membuat instance objek baru menggunakan fungsi konstruktor yang diberikan.
Pada dasarnya, apa yang dikatakan adalah bahwa setiap layanan Angular terdaftar menggunakan $provide.provider()
, tetapi ada metode "pintasan" untuk layanan yang lebih sederhana (dua di antaranya adalah service()
dan factory()
).
Semuanya "bermuara" pada layanan, jadi tidak ada bedanya metode mana yang Anda gunakan (selama persyaratan untuk layanan Anda dapat dicakup oleh metode itu).
BTW, provider
vs service
vs factory
adalah salah satu konsep yang paling membingungkan untuk pendatang baru Angular, tetapi untungnya ada banyak sumber daya (di SO) untuk mempermudah. (Cari saja.)
(Saya harap itu menyelesaikannya - beri tahu saya jika tidak.)