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


349

Teraz, że różnica wydajności pomiędzy $broadcasti $emitzostała wyeliminowana, nie ma żadnych powodów, aby wolą $scope.$emitsię $rootScope.$broadcast?

Są różne, tak.

$emit jest ograniczona do hierarchii zakresu (w górę) - może to być dobre, jeśli pasuje do twojego projektu, ale wydaje mi się to dość arbitralnym ograniczeniem.

$rootScope.$broadcastdziała we wszystkich, którzy zdecydują się słuchać tego wydarzenia, co jest bardziej rozsądnym ograniczeniem w mojej opinii.

Czy coś brakuje?

EDYTOWAĆ:

Aby wyjaśnić w odpowiedzi na odpowiedź, nie chodzi o kierunek wysyłki. $scope.$emitwywołuje zdarzenie w górę, i $scope.$broadcast- w dół. Ale dlaczego nie zawsze $rootScope.$broadcastdocierać do wszystkich zamierzonych słuchaczy?


3
toddmotto.com/… ma to wszystko
— Divya MV

Odpowiedzi:


1155

tl; dr (ten tl; dr pochodzi z odpowiedzi @ sp00m poniżej)

$emitwywołuje zdarzenie w górę ... $broadcastwywołuje zdarzenie w dół

Szczegółowe wyjaśnienie

$rootScope.$emitpozwala tylko innym $rootScopesłuchaczom go złapać. Jest to dobre, gdy nie chcesz, $scopeaby każdy to otrzymał. Przeważnie komunikacja na wysokim poziomie. Pomyśl o tym, jak dorośli rozmawiają ze sobą w pokoju, aby dzieci ich nie słyszały.

$rootScope.$broadcastto metoda, która pozwala usłyszeć prawie wszystko. Byłoby to odpowiednikiem krzyku rodziców, że obiad jest gotowy, więc wszyscy w domu to słyszą.

$scope.$emitjest to, kiedy chcesz tego $scopei wszystkich jego rodziców i $rootScopeusłyszeć wydarzenie. To dziecko narzeka na rodziców w domu (ale nie w sklepie spożywczym, w którym słyszą inne dzieci).

$scope.$broadcastjest dla $scopesiebie i swoich dzieci. To dziecko szepcze pluszowym zwierzakom, żeby ich rodzice nie słyszeli.


3
@NewDev Powodem jest to, że często na stronie powtarzają się zakresy. Jeśli masz dwa lub więcej zakresów reprezentujących różne instancje danych - np. Listę rekordów pacjentów na stronie, każdy z własnym zakresem - nie będzie działać transmisja z katalogu głównego zdarzenia przeznaczonego tylko dla jednego z nich zakresy Unikanie $rootScopetransmisji tam, gdzie to możliwe, umożliwia lepsze ponowne wykorzystanie.
— Tim Rogers,

4
Nic, co powiedziałeś, nie jest złe, ale sposób na uogólnienie, że $ emituje dokument do zakresów potomnych, a $ emituje dokument do zakresów nadrzędnych. Oba wyzwalają wszystkich detektorów podłączonych do bieżącego zakresu.
— Eric

123
Użyty przykład jest świetny!
— Assaf

72
Łał! Nawet dzieci mogą to zrozumieć! Niesamowite :)
— Navaneeth

3
Idealny przykład, uwielbiam wyjaśnienie
— Robin-Hoodie

104

Nie wykonują tego samego zadania: $emitwywołują zdarzenie w górę poprzez hierarchię zasięgu, a $broadcastzdarzenie w dół do wszystkich zakresów potomnych.


2
Tak, zauważyłem to w pytaniu (być może mógłbym jasno powiedzieć o kierunku wysyłki). Ale zauważyłem również, że jest to raczej arbitralne ograniczenie. Jeśli mogę dotrzeć do mojego „słuchacza”, dlaczego nie zawsze mogę to zrobić w dół $rootScope?
— Nowy Dev,

Ponieważ emisja $ nie wpłynie na zakresy potomne lub siostrzane zakresu. Po prostu odwzorowują typy propagacji zdarzeń w javascript - przechwytywanie i propagowanie. $ broadcast służy do przechwytywania, a $ emit służy do propagacji. Jest na pozór starożytny artykuł quirksmode, który całkiem dobrze wyjaśnia różnicę: quirksmode.org/js/events_order.html
— Alan L.

77

Wykonałem następującą grafikę z następującego linku: https://toddmotto.com/all-about-angulars-emit-broadcast-on-publish-subscribing/

Zakres, rootScope, emisja, emisja

Jak widać, $rootScope.$broadcasttrafia o wiele więcej słuchaczy niż $scope.$emit.

Również $scope.$emitefekt bulgotania można anulować, $rootScope.$broadcastale nie można.


24
Widzę dużo strzał.
— Mars Robertson,

4
@MichalStefanow Jestem fanem wizualnych odpowiedzi :)
— Maria Ines Parnisari

@mparnisari:. $ broadcast (nazwa, argumenty) - Transmisja zdarzenia w dół do zakresu $ wszystkich dzieci. $ emit (nazwa, argumenty) - Emisja zdarzenia w górę hierarchii $ do wszystkich rodziców, w tym $ rootScope
— CodeMan

19

wprowadź opis zdjęcia tutaj

$ scope. $ emit: Ta metoda wywołuje zdarzenie w górę (od dziecka do rodzica)

wprowadź opis zdjęcia tutaj $ scope. $ broadcast: Metoda wywołuje zdarzenie w dół (od rodzica do dziecka) do wszystkich kontrolerów potomnych.

wprowadź opis zdjęcia tutaj $ scope. $ on: Metoda rejestruje się w celu odsłuchania jakiegoś zdarzenia. Wszystkie kontrolery, które nasłuchują tego zdarzenia, otrzymują powiadomienie o emisji lub emitują na podstawie tego, gdzie mieszczą się one w hierarchii dziecko-rodzic.

Zdarzenie $ emit może zostać anulowane przez każdego z $ zakres, który nasłuchuje zdarzenia.

$ On zapewnia metodę „stopPropagation”. Wywołanie tej metody może uniemożliwić dalszą propagację zdarzenia.

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

W przypadku zakresów rodzeństwa (zakresów, które nie znajdują się w bezpośredniej hierarchii rodzic-dziecko), wówczas $ emit i $ broadcast nie będą komunikować się z zasięgami rodzeństwa.

wprowadź opis zdjęcia tutaj

Więcej informacji można znaleźć na stronie http://yogeshtutorials.blogspot.in/2015/12/event-based-communication-between-angularjs-controllers.html


Link do rozwiązania jest mile widziany, ale upewnij się, że Twoja odpowiedź jest przydatna bez niego: dodaj kontekst wokół linku, aby inni użytkownicy mieli pojęcie, co to jest i dlaczego tam jest, a następnie zacytuj najbardziej odpowiednią część strony, którą „ ponowne linkowanie na wypadek, gdyby strona docelowa była niedostępna. Odpowiedzi, które są niewiele więcej niż link, mogą zostać usunięte.
— Baum mit Augen

Celem było zapewnienie działającego plunkera, jednak dodałem tutaj odpowiedni opis.
— Jogesh

3

@Eddie udzielił idealnej odpowiedzi na zadane pytanie. Chciałbym jednak zwrócić uwagę na bardziej wydajne podejście Pub / Sub.

Jak sugeruje ta odpowiedź,

Podejście $ broadcast / $ on nie jest zbyt wydajne, ponieważ nadaje do wszystkich zakresów (albo w jednym kierunku, albo w obu kierunkach hierarchii zakresu). Podczas gdy podejście Pub / Sub jest znacznie bardziej bezpośrednie. Tylko subskrybenci odbierają zdarzenia, więc nie musi działać w każdym zakresie w systemie.

możesz użyć angular-PubSubmodułu kątowego. po dodaniu PubSubmodułu do zależności aplikacji możesz użyć PubSubusługi do subskrybowania i anulowania subskrypcji wydarzeń / tematów.

Łatwa subskrypcja:

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

});

Łatwe do opublikowania

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

Aby anulować subskrypcję, użyj PubSub.unsubscribe(sub); LUB PubSub.unsubscribe('event-name');.

UWAGA Nie zapomnij anulować subskrypcji, aby uniknąć wycieków pamięci.


2

Użyj RxJS w usłudze

A może na przykład w sytuacji, gdy masz usługę, która utrzymuje stan. Jak mogę wcisnąć zmiany w tej usłudze, a inne losowe komponenty na stronie powinny wiedzieć o takiej zmianie? Ostatnio zmagam się z rozwiązaniem tego problemu

Zbuduj usługę z rozszerzeniami RxJS dla 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);
      }
  };
});

Następnie subskrybuj zmiany.

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();
  };
});

Klienci mogą subskrybować zmiany za pomocą, DataService.subscribea producenci mogą wprowadzać zmiany za pomocą DataService.set.

DEMO na PLNKR .

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.