$ rootScope. $ broadcast vs. $ scope. $ emit

349

Sekarang bahwa perbedaan kinerja antara $broadcastdan $emittelah dieliminasi, apakah ada alasan untuk lebih memilih $scope.$emitke $rootScope.$broadcast?

Mereka berbeda, ya.

$emit terbatas pada hierarki lingkup (ke atas) - ini mungkin bagus, jika cocok dengan desain Anda, tetapi bagi saya sepertinya pembatasan yang agak sewenang-wenang.

$rootScope.$broadcastbekerja di semua yang memilih untuk mendengarkan acara tersebut, yang merupakan batasan yang lebih masuk akal dalam pikiran saya.

Apakah saya melewatkan sesuatu?

EDIT:

Untuk mengklarifikasi sebagai jawaban atas jawaban, arah pengiriman bukanlah masalah yang saya cari. $scope.$emitmengirim acara ke atas, dan $scope.$broadcast- ke bawah. Tetapi mengapa tidak selalu digunakan $rootScope.$broadcastuntuk menjangkau semua pendengar yang dituju?

Dev baru
sumber
3
toddmotto.com/… memiliki semuanya
Divya MV

Jawaban:

1155

tl; dr (tl; dr ini dari jawaban @ sp00m di bawah)

$emitmengirim acara ke atas ... $broadcastmengirim acara ke bawah

Penjelasan detail

$rootScope.$emithanya membiarkan $rootScopependengar lain menangkapnya. Ini bagus ketika Anda tidak ingin setiap orang $scopemendapatkannya. Sebagian besar komunikasi tingkat tinggi. Anggap saja sebagai orang dewasa berbicara satu sama lain di sebuah ruangan sehingga anak-anak tidak dapat mendengar mereka.

$rootScope.$broadcastadalah metode yang memungkinkan hampir semua orang mendengarnya. Ini akan sama dengan orang tua yang berteriak bahwa makan malam sudah siap sehingga semua orang di rumah mendengarnya.

$scope.$emitadalah ketika Anda ingin itu $scopedan semua orang tuanya dan $rootScopemendengar acara tersebut. Ini adalah anak yang merengek kepada orang tua mereka di rumah (tetapi tidak di toko kelontong tempat anak-anak lain dapat mendengar).

$scope.$broadcastadalah untuk $scopedirinya sendiri dan anak-anaknya. Ini adalah anak yang berbisik kepada boneka binatangnya sehingga orang tua mereka tidak bisa mendengar.

Eddie Monge Jr
sumber
3
@NewDev Alasannya adalah karena seringkali Anda memiliki pengulangan cakupan pada halaman. Jika Anda memiliki dua atau lebih cakupan yang mewakili berbagai contoh data - misalnya daftar catatan pasien pada halaman, masing-masing dengan cakupannya sendiri - maka itu tidak akan berfungsi untuk menyiarkan dari root suatu peristiwa yang dimaksudkan hanya untuk salah satu dari mereka lingkup. Menghindari $rootScopesiaran jika memungkinkan memungkinkan penggunaan kembali yang lebih baik.
Tim Rogers
4
Tidak ada yang Anda katakan salah, tetapi cara untuk menggeneralisasi bahwa $ emit menurunkan dokumen ke cakupan anak dan $ emit naik dokumen ke cakupan orangtua. Keduanya akan memicu pendengar yang terikat pada ruang lingkup saat ini.
Eric
123
Contoh yang Anda gunakan luar biasa!
Assaf
72
Wow! Bahkan anak-anak pun bisa mengerti ini! Luar biasa :)
Navaneeth
3
Contoh sempurna, suka penjelasannya
Robin-Hoodie
104

Mereka tidak melakukan pekerjaan yang sama: $emitmengirimkan acara ke atas melalui hierarki lingkup, sementara $broadcastmengirimkan acara ke bawah ke semua cakupan anak.

sp00m
sumber
2
Ya, saya perhatikan bahwa dalam pertanyaan (mungkin saya bisa menjelaskan tentang arah pengiriman). Tetapi saya juga mencatat bahwa itu adalah pembatasan yang agak sewenang-wenang. Jika saya dapat mencapai "pendengar" saya, mengapa saya tidak bisa selalu melakukan ini dari bawah $rootScope?
Dev Baru
Karena $ emit tidak akan memengaruhi lingkup anak atau saudara kandungnya. Ini hanya memetakan ke jenis propagasi acara javascript - menangkap dan menggelegak. $ broadcast digunakan untuk menangkap dan $ emit digunakan untuk menggelegak. Ada artikel quirksmode yang tampaknya kuno yang menjelaskan perbedaannya dengan cukup baik: quirksmode.org/js/events_order.html
Alan L.
77

Saya membuat gambar berikut dari tautan berikut: https://toddmotto.com/all-about-angulars-emit-broadcast-on-publish-subscribing/

Lingkup, rootScope, memancarkan, siaran

Seperti yang Anda lihat, $rootScope.$broadcasthit lebih banyak pendengar daripada $scope.$emit.

Juga, $scope.$emitefek menggelegak dapat dibatalkan, sedangkan $rootScope.$broadcasttidak bisa.

Maria Ines Parnisari
sumber
24
Saya melihat banyak panah.
Mars Robertson
4
@MichalStefanow Saya penggemar jawaban visual :)
Maria Ines Parnisari
@parparari:. $ broadcast (name, args) - Siarkan acara turun melalui $ lingkup semua anak. $ emit (nama, args) - Keluarkan suatu acara tingkatkan hirarki $ lingkup untuk semua orang tua, termasuk $ rootScope
CodeMan
19

masukkan deskripsi gambar di sini

$ scope. $ emit: Metode ini mengirimkan peristiwa ke arah atas (dari anak ke orangtua)

masukkan deskripsi gambar di sini $ scope. $ broadcast: Metode mengirimkan acara ke arah bawah (dari orangtua ke anak) ke semua pengontrol anak.

masukkan deskripsi gambar di sini $ scope. $ on: Metode mendaftar untuk mendengarkan suatu acara. Semua pengendali yang mendengarkan acara itu mendapatkan pemberitahuan siaran atau memancarkan berdasarkan di mana mereka cocok dalam hirarki anak-orangtua.

Acara $ emit dapat dibatalkan oleh salah satu dari $ lingkup yang mendengarkan acara tersebut.

$ On menyediakan metode "stopPropagation". Dengan memanggil metode ini, acara dapat dihentikan dari penyebaran lebih lanjut.

Plunker: https://embed.plnkr.co/0Pdrrtj3GEnMp2UpILp4/

Dalam hal ruang lingkup saudara (ruang lingkup yang tidak dalam hirarki orangtua-anak langsung) maka $ emit dan $ broadcast tidak akan berkomunikasi dengan ruang lingkup saudara.

masukkan deskripsi gambar di sini

Untuk detail lebih lanjut silakan merujuk ke http://yogeshtutorials.blogspot.in/2015/12/event-based-communication-between-angularjs-controllers.html

Yogesh
sumber
Tautan ke suatu solusi disambut baik, tetapi harap pastikan jawaban Anda bermanfaat tanpanya: tambahkan konteks di sekitar tautan sehingga teman-teman Anda akan mengetahui apa itu dan mengapa ada, lalu kutip bagian yang paling relevan dari halaman yang Anda tuju. menghubungkan kembali jika seandainya halaman target tidak tersedia. Jawaban yang sedikit lebih dari sebuah tautan dapat dihapus.
Baum mit Augen
Tujuannya adalah untuk menyediakan plunker yang berfungsi, namun, saya telah menambahkan deskripsi yang sesuai di sini.
Yogesh
3

@ Eddie telah memberikan jawaban sempurna dari pertanyaan yang diajukan. Tetapi saya ingin menarik perhatian untuk menggunakan pendekatan Pub / Sub yang lebih efisien.

Seperti yang disarankan oleh jawaban ini ,

Pendekatan $ broadcast / $ on tidak terlalu efisien karena ia menyiarkan ke semua cakupan (Baik dalam satu arah atau kedua arah hierarki Lingkup). Sementara pendekatan Pub / Sub jauh lebih langsung. Hanya pelanggan yang mendapatkan acara, sehingga tidak pergi ke setiap ruang lingkup dalam sistem untuk membuatnya berfungsi.

Anda dapat menggunakan angular-PubSubmodul sudut. setelah Anda menambahkan PubSubmodul ke ketergantungan aplikasi Anda, Anda dapat menggunakan PubSublayanan untuk berlangganan dan berhenti berlangganan acara / topik.

Mudah berlangganan:

// Subscribe to event
var sub = PubSub.subscribe('event-name', function(topic, data){

});

Mudah diterbitkan

PubSub.publish('event-name', {
    prop1: value1,
    prop2: value2
});

Untuk berhenti berlangganan, gunakan PubSub.unsubscribe(sub);ATAU PubSub.unsubscribe('event-name');.

CATATAN Jangan lupa berhenti berlangganan untuk menghindari kebocoran memori.

vinesh
sumber
2

Gunakan RxJS dalam Layanan

Bagaimana dengan situasi di mana Anda memiliki Layanan yang memiliki status sebagai contoh. Bagaimana saya bisa mendorong perubahan ke Layanan itu, dan komponen acak lainnya pada halaman menyadari perubahan seperti itu? Telah berjuang dengan mengatasi masalah ini belakangan ini

Bangun layanan dengan RxJS Extensions for Angular .

<script src="//unpkg.com/angular/angular.js"></script>
<script src="//unpkg.com/rx/dist/rx.all.js"></script>
<script src="//unpkg.com/rx-angular/dist/rx.angular.js"></script>
var app = angular.module('myApp', ['rx']);

app.factory("DataService", function(rx) {
  var subject = new rx.Subject(); 
  var data = "Initial";

  return {
      set: function set(d){
        data = d;
        subject.onNext(d);
      },
      get: function get() {
        return data;
      },
      subscribe: function (o) {
         return subject.subscribe(o);
      }
  };
});

Maka cukup berlangganan perubahan.

app.controller('displayCtrl', function(DataService) {
  var $ctrl = this;

  $ctrl.data = DataService.get();
  var subscription = DataService.subscribe(function onNext(d) {
      $ctrl.data = d;
  });

  this.$onDestroy = function() {
      subscription.dispose();
  };
});

Klien dapat berlangganan perubahan dengan DataService.subscribedan produsen dapat mendorong perubahan dengan DataService.set.

The DEMO pada PLNKR .

georgeawg
sumber