$ rootScope. $ Broadcast vs. $ Scope. $ emit

349

Gibt es einen Grund, dies vorzuziehen , nachdem der Leistungsunterschied zwischen $broadcastund $emitbeseitigt wurde ?$scope.$emit$rootScope.$broadcast

Sie sind anders, ja.

$emit ist auf die Bereichshierarchie (nach oben) beschränkt - dies mag gut sein, wenn es zu Ihrem Design passt, aber es scheint mir eine eher willkürliche Einschränkung zu sein.

$rootScope.$broadcastfunktioniert über alle, die sich dafür entscheiden , das Ereignis anzuhören, was für mich eine vernünftigere Einschränkung darstellt.

Vermisse ich etwas

BEARBEITEN:

Um als Antwort auf eine Antwort zu verdeutlichen, ist die Richtung des Versands nicht das Problem, nach dem ich suche. $scope.$emitsendet das Ereignis nach oben und $scope.$broadcast- nach unten. Aber warum nicht immer verwenden $rootScope.$broadcast, um alle beabsichtigten Zuhörer zu erreichen?

New Dev
quelle
3
toddmotto.com/… hat alles
Divya MV

Antworten:

1155

tl; dr (dieses tl; dr stammt aus der Antwort von @ sp00m unten)

$emitSendet ein Ereignis nach oben ... $broadcastSendet ein Ereignis nach unten

Ausführliche Erklärung

$rootScope.$emitlässt nur andere $rootScopeHörer es fangen. Das ist gut, wenn Sie nicht wollen, dass jeder $scopees bekommt. Meistens eine Kommunikation auf hohem Niveau. Stellen Sie sich das als Erwachsene vor, die in einem Raum miteinander sprechen, damit die Kinder sie nicht hören können.

$rootScope.$broadcastist eine Methode, mit der so ziemlich alles es hören kann. Dies wäre das Äquivalent zu Eltern, die schreien, dass das Abendessen fertig ist, damit jeder im Haus es hört.

$scope.$emitist, wenn Sie das $scopeund alle seine Eltern wollen und $rootScopedas Ereignis zu hören. Dies ist ein Kind, das zu Hause zu seinen Eltern jammert (aber nicht in einem Lebensmittelgeschäft, in dem andere Kinder hören können).

$scope.$broadcastist für $scopesich und seine Kinder. Dies ist ein Kind, das seinen Stofftieren zuflüstert, damit ihre Eltern nichts hören können.

Eddie Monge Jr.
quelle
3
@NewDev Der Grund dafür ist, dass Sie häufig Bereiche auf der Seite wiederholen. Wenn Sie zwei oder mehr Bereiche haben, die unterschiedliche Dateninstanzen darstellen - z. B. eine Liste von Patientenakten auf einer Seite mit jeweils eigenem Bereich -, funktioniert es nicht, ein Ereignis, das nur für einen dieser Fälle vorgesehen ist, vom Stamm aus zu senden Bereiche. Wenn Sie $rootScopeSendungen nach Möglichkeit vermeiden , können Sie sie besser wiederverwenden.
Tim Rogers
4
Nichts, was Sie gesagt haben, ist falsch, aber eine Möglichkeit, es zu verallgemeinern, dass $ emit das Dokument in untergeordnete Bereiche und $ emit das Dokument in übergeordnete Bereiche überträgt. Beide lösen alle Listener aus, die an den aktuellen Bereich angehängt sind.
Eric
123
Das Beispiel, das Sie verwendet haben, ist großartig!
Assaf
72
Beeindruckend! Sogar Kinder können das verstehen! Erstaunlich :)
Navaneeth
3
Perfektes Beispiel, liebe die Erklärung
Robin-Hoodie
104

Sie erledigen nicht den gleichen Job: Sie $emitsenden ein Ereignis über die Bereichshierarchie nach oben , während $broadcastsie ein Ereignis nach unten an alle untergeordneten Bereiche senden.

sp00m
quelle
2
Ja, das habe ich in der Frage vermerkt (vielleicht hätte ich die Versandrichtung klarstellen können). Ich habe aber auch festgestellt, dass dies eine eher willkürliche Einschränkung ist. Wenn ich meinen "Zuhörer" erreichen kann, warum kann ich das nicht immer abwärts tun $rootScope?
New Dev
Weil ein $ emit keine Auswirkungen auf die untergeordneten oder geschwisterlichen Bereiche eines Bereichs hat. Diese werden nur den Ereignisausbreitungstypen von Javascript zugeordnet - Erfassen und Sprudeln. $ Broadcast wird zum Erfassen und $ emit zum Sprudeln verwendet. Es gibt einen scheinbar uralten Artikel im Quirksmode, der den Unterschied ziemlich gut erklärt: quirksmode.org/js/events_order.html
Alan L.
77

Ich habe die folgende Grafik aus dem folgenden Link gemacht: https://toddmotto.com/all-about-angulars-emit-broadcast-on-publish-subscribing/

Scope, rootScope, emittieren, senden

Wie Sie sehen können, $rootScope.$broadcasttrifft viel mehr Zuhörer als $scope.$emit.

Außerdem $scope.$emitkann der Blaseneffekt aufgehoben werden, während $rootScope.$broadcastdies nicht möglich ist.

Maria Ines Parnisari
quelle
24
Ich sehe viele Pfeile.
Mars Robertson
4
@ MichaelStefanow Ich bin ein Fan von visuellen Antworten :)
Maria Ines Parnisari
@parnisari :. $ Broadcast (Name, Argumente) - Übertragen Sie ein Ereignis über den $ -Bereich aller untergeordneten
Elemente.
19

Geben Sie hier die Bildbeschreibung ein

$ scope. $ emit: Diese Methode löst das Ereignis nach oben aus (vom Kind zum Elternteil).

Geben Sie hier die Bildbeschreibung ein $ scope. $ Broadcast: Die Methode sendet das Ereignis in Abwärtsrichtung (von übergeordnet zu untergeordnet) an alle untergeordneten Controller.

Geben Sie hier die Bildbeschreibung ein $ scope. $ on: Die Methode registriert sich, um ein Ereignis abzuhören. Alle Controller, die dieses Ereignis abhören, erhalten eine Benachrichtigung über die Übertragung oder Ausgabe, basierend darauf, wo diese in die Hierarchie zwischen Kind und Eltern passen.

Das $ emit-Ereignis kann von jedem $ -Bereich abgebrochen werden, der das Ereignis abhört.

Das $ on stellt die Methode "stopPropagation" bereit. Durch Aufrufen dieser Methode kann verhindert werden, dass sich das Ereignis weiter ausbreitet.

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

Bei Geschwisterbereichen (den Bereichen, die nicht in der direkten Eltern-Kind-Hierarchie enthalten sind) kommunizieren $ emit und $ Broadcast nicht mit den Geschwisterbereichen.

Geben Sie hier die Bildbeschreibung ein

Weitere Informationen finden Sie unter http://yogeshtutorials.blogspot.in/2015/12/event-based-communication-between-angularjs-controllers.html

Yogesh
quelle
Ein Link zu einer Lösung ist willkommen, aber stellen Sie bitte sicher, dass Ihre Antwort ohne sie nützlich ist: Fügen Sie dem Link einen Kontext hinzu, damit Ihre Mitbenutzer eine Vorstellung davon haben, was es ist und warum es dort ist, und zitieren Sie dann den relevantesten Teil der Seite, die Sie verwenden. erneutes Verknüpfen mit, falls die Zielseite nicht verfügbar ist. Antworten, die kaum mehr als ein Link sind, können gelöscht werden.
Baum mit Augen
Das Ziel war es, den funktionierenden Plunker bereitzustellen, ich habe hier jedoch die entsprechende Beschreibung hinzugefügt.
Yogesh
3

@Eddie hat die gestellte Frage perfekt beantwortet. Ich möchte jedoch darauf aufmerksam machen, dass Pub / Sub effizienter eingesetzt wird.

Wie diese Antwort nahelegt,

Der Ansatz $ Broadcast / $ on ist nicht besonders effizient, da er an alle Bereiche sendet (entweder in eine Richtung oder in beide Richtungen der Bereichshierarchie). Während der Pub / Sub-Ansatz viel direkter ist. Nur Abonnenten erhalten die Ereignisse, sodass nicht jeder Bereich im System funktioniert.

Sie können ein angular-PubSubWinkelmodul verwenden. Sobald Sie PubSubIhrer App-Abhängigkeit ein Modul hinzugefügt haben , können Sie mithilfe des PubSubDienstes Ereignisse / Themen abonnieren und abbestellen.

Einfach zu abonnieren:

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

});

Einfach zu veröffentlichen

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

Verwenden Sie zum Abbestellen PubSub.unsubscribe(sub);OR PubSub.unsubscribe('event-name');.

HINWEIS Vergessen Sie nicht, sich abzumelden, um Speicherlecks zu vermeiden.

Weinreben
quelle
2

Verwenden Sie RxJS in einem Dienst

Was ist mit einer Situation, in der Sie beispielsweise einen Dienst haben, der den Status "Halten" hat? Wie kann ich Änderungen an diesem Service vornehmen, und andere zufällige Komponenten auf der Seite können sich einer solchen Änderung bewusst sein? Ich hatte in letzter Zeit Probleme, dieses Problem anzugehen

Erstellen Sie einen Dienst mit RxJS-Erweiterungen für 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);
      }
  };
});

Dann abonnieren Sie einfach die Änderungen.

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

Kunden können Änderungen mit abonnieren DataService.subscribeund Produzenten können Änderungen mit vorantreiben DataService.set.

Die DEMO auf PLNKR .

georgeawg
quelle