Meneruskan cakupan saat ini ke Layanan AngularJS

106

Apakah benar untuk meneruskan "arus" $scopeke layanan AngularJS?

Saya berada dalam situasi di mana saya memiliki $ service karena mengetahui itu dikonsumsi hanya oleh satu pengontrol, dan saya ingin memiliki referensi ke ruang lingkup pengontrol dalam metode $ service itu sendiri.

Apakah ini benar secara filosofis ?

Atau lebih baik saya menyiarkan acara ke $ rootScope dan kemudian membuat pengontrol saya mendengarkannya?

SC
sumber
1
Dapatkah Anda memberi tahu kami secara lebih spesifik tentang apa yang Anda coba lakukan? Mungkin mendorong ruang lingkup ke layanan tidak diperlukan sama sekali?
ganaraj
Yah, tidak terlalu sulit. Sederhananya, saya ingin dapat mengakses $scopeproperti dan menelepon $scope.$applysaat diperlukan.
SC
Plus, katakanlah saya ingin menerapkan perubahan yang berasal dari $ service ke $ scope. Semoga lebih jelas sekarang.
SC
8
Saya sarankan Anda meletakkan properti $ scope yang Anda ingin layanan Anda akses ke layanan itu sendiri (alih-alih memilikinya di controller). Layanan adalah tempat yang lebih baik untuk menyimpan model / data daripada pengontrol.
Mark Rajcok
@MarkRajcock Saya mencoba memahami masalah ini juga. Saat ini saya hanya memanggil layanan dan melampirkan data yang disajikan ke pengontrol $scope... bagaimana pengontrol langsung mengakses data dalam layanan dan meneruskannya ke tampilan tanpa melakukan ini?
drjimmie1976

Jawaban:

67

Untuk memberi tahu pengontrol saat terjadi asinkronisasi, gunakan janji Angular .

Untuk memprovokasi $apply, Anda tidak memerlukan scope, Anda bisa memanggil $rootScope.$apply, karena tidak ada perbedaan memanggilnya dalam lingkup tertentu atau di root.

Mengenai pembacaan variabel, akan lebih baik jika Anda menerima parameter. Tetapi Anda juga dapat membacanya dari ruang lingkup sebagai parameter objek, tetapi saya akan menggunakan parameter, yang akan membuat antarmuka layanan Anda jauh lebih jelas.

Caio Cunha
sumber
Saya pikir ini adalah jawaban yang lebih baik dalam memecahkan keraguan pemula AngularJS saya.
SC
@Caio Cunha Bisakah Anda menjelaskan mengapa melewatkan suatu cakupan adalah ide yang bagus? Saya mengalami masalah ini, saya ingin menambahkan beberapa hal $scopemelalui panggilan ke layanan menggunakan executeSql()fungsi async . Melihat ke 3 opsi (1) gunakan callback pada fungsi async, lalu panggil $scope.$apply... ini berfungsi, tetapi jelek (2) teruskan $scopeke fungsi asinkron, lalu panggil theScope.$apply()... ini juga berfungsi (3) gunakan janji. ..belum mencoba ini. Mengapa janji adalah cara terbaik? Terima kasih!
drjimmie1976
15

Saya akan mengatakan jika fungsionalitas Anda khusus untuk satu pengontrol saja daripada Anda tidak memerlukan layanan.

Tugas pengontrol adalah memanipulasi model tertentu sedangkan layanan harus menangani tugas global. Saya lebih suka berpegang pada paradigma ini daripada mencampurkan semuanya.

Ini yang dikatakan dokumen

Layanan

Layanan angular adalah lajang yang melakukan tugas-tugas khusus yang umum untuk aplikasi web

Kontroler

Di Angular, pengontrol adalah fungsi JavaScript (jenis / kelas) yang digunakan untuk menambah instance Scope sudut, tidak termasuk cakupan root.

PS: Selain itu jika Anda perlu mencerna, Anda juga dapat menyuntikkan $ rootScope dalam layanan Anda.

F Lekscha
sumber
2
Terima kasih. Jawaban yang bagus. Mendalami situasi saya, intinya adalah saya menggunakan Service karena saya ingin singleton. Hanya ada satu pengontrol yang menggunakan layanan, tetapi pengontrol ini dapat dibuat beberapa kali selama siklus hidup aplikasi, jadi saya benar-benar ingin Layanan selalu dalam keadaan yang sama.
SC
Bagaimanapun, klarifikasi tentang panggilan $applyatau $digestke $ rootScope sangat masuk akal bagi saya.
SC
1
Saya masih akan memisahkannya menjadi Layanan untuk pengujian.
bluehallu
Jika fungsinya khusus untuk satu instance pengontrol, maka Anda dapat melewati penerapan layanan, tetapi sebaliknya tidak karena Anda mengorbankan kemampuan untuk membagi status di antara instance tersebut. Lebih jauh lagi, hanya karena ada satu jenis pengontrol hari ini, tidak berarti bahwa tidak akan ada pengontrol berbeda yang dapat memanfaatkan fungsionalitas besok. Selain itu, layanan dapat mencegah pengontrol membengkak. Jadi ini bukan pertanyaan tentang apakah ada satu pengontrol, tetapi apa fungsinya yang dipertanyakan.
Nick
9

Iya. Anda bisa meneruskan $ scope ke layanan saat Anda menginisialisasinya. Dalam konstruktor layanan, Anda dapat menetapkan cakupan ke sesuatu seperti this._scope dan kemudian mereferensikan cakupan dalam layanan!

angular.module('blah').controller('BlahCtrl', function($scope, BlahService) {

    $scope.someVar = 4;

    $scope.blahService = new blahService($scope);

});

angular.module('blah').factory('blahService', function() {

    //constructor
    function blahService(scope) {
        this._scope = scope;

        this._someFunction()
    }

    //wherever you'd reference the scope
    blahService.prototype._someFunction = function() {

        this._scope['someVar'] = 5;

    }

    return blahService;

});
pengguna12121234
sumber
1
+1, bagaimanapun, saya ingin melihat cara untuk secara otomatis mengetahui setiap pengontrol setiap kali pengontrol $scopeyang diberikan menginjeksi layanan - sehingga tidak perlu memanggil metode pada layanan dan meneruskannya secara manual $scope.
Cody
2
@Cody Saya tidak merekomendasikan itu karena bertentangan dengan Dependency Injection
Coldstar
Setuju, +1 untuk menembak saya! Mungkin tukang daging DIP juga - saya akan mengatakan, dengan risiko menjadi mubazir.
Cody
Anda mencampurkan layanan dengan pabrik di sini. Solusi ini menggunakan pabrik, yang berbeda dari layanan. Perbedaan utamanya adalah bahwa layanan mengembalikan objek (tunggal). Sedangkan pabrik mengembalikan fungsi, yang bisa dibuat instantiated ( new MyFunction()). Pertanyaannya adalah tentang layanan, di mana menelepon newbukanlah suatu pilihan.
Karvapallo
@Tokopedia Sebagai titik tandingan, saya yakin layanan sudut mengacu pada pabrik, layanan, dan penyedia (ng-wat)?
pengguna12121234
6

Saya pribadi percaya bahwa meneruskan $scopelayanan adalah ide yang buruk , karena ini menciptakan referensi melingkar: pengontrol bergantung pada layanan dan layanan bergantung pada cakupan pengontrol.

Selain membingungkan dalam hal hubungan, hal-hal seperti ini akhirnya menghalangi pengumpul sampah.

Pendekatan yang saya sukai adalah meletakkan objek domain dalam lingkup pengontrol dan meneruskannya ke layanan. Dengan cara ini layanan berfungsi terlepas apakah itu digunakan di dalam pengontrol atau mungkin di dalam layanan lain di masa mendatang.

Misalnya, jika layanan seharusnya mendorong dan memunculkan elemen dari array errors, kode saya adalah:

var errors = [];
$scope.errors = errors;
$scope.myService = new MyService(errors);

Layanan kemudian berinteraksi dengan pengontrol dengan mengoperasikannya errors. Tentu saja saya harus berhati-hati untuk tidak pernah menghapus seluruh referensi array, tetapi pada akhirnya itu adalah masalah JS umum.

Saya tidak pernah ingin menggunakan penyiaran, $applydan / atau hal serupa, karena praktek OO yang baik akan selalu mengalahkan sihir Angular apa pun.

Marco Faustinelli
sumber
1
Apakah kode ini ada bedanya dengan yang ini ?:$scope.errors = []; $scope.myService = new MyService($scope.errors);
Soldeplata Saketos
@SoldeplataSaketos - Ya, benar. errorshidup mandiri dari $scope. Itulah inti dari jawaban ini. Tolong periksa tautan yang saya berikan dalam teks. Bersulang.
Marco Faustinelli
1
Jika saya memahami dengan benar kode Anda, $scope.errorsitu menunjuk ke var errors, dan kesalahan variabel tampak berlebihan bagi saya, karena itu hanya penunjuk lain. Satu situasi yang sama saya bisa memikirkan dan bahwa itu terang-terangan berlebihan adalah potongan kode ini: const errors = errors2 = errors3 = []; $scope.errors = errors;. Apakah Anda setuju bahwa hanya dengan potongan kode yang Anda berikan tampaknya itu var errors = []berlebihan?
Soldeplata Saketos
Tidak, tidak. Saya ulangi kata demi kata: errorshidup secara mandiri $scope. Anda perlu memahami apa itu objek domain, serta apa itu vartugas. Jika tautan yang saya berikan tidak cukup, ada banyak materi lain yang tersedia.
Marco Faustinelli
Nah, itu hanya akan bergantung pada implementasi fungsinya MyService(errors). Dalam pemahaman saya, layanan harus menghasilkan array logging berdasarkan parameter (dalam hal ini pointer). Bagi saya itu pola yang buruk, karena layanannya adalah lajang bersudut. Jika implementasi layanan diprogram dengan baik, itu harus menghasilkan array dalam variabel internal (untuk tetap menjadi tunggal). Oleh karena itu, tidak ada gunanya menginisialisasi variabel di luar layanan.
Soldeplata Saketos