$ rootScope. $ broadcast vs. $ scope. $ emettono


349

Ora che la differenza di prestazioni tra $broadcaste $emitè stato eliminato, non v'è alcun motivo per preferire $scope.$emita$rootScope.$broadcast ?

Sono diversi, sì.

$emit è limitato alla gerarchia dell'ambito (verso l'alto) - questo può essere buono, se si adatta al tuo progetto, ma mi sembra una restrizione piuttosto arbitraria.

$rootScope.$broadcastfunziona con tutti quelli che scelgono di ascoltare l'evento, che è una restrizione più sensata nella mia mente.

Mi sto perdendo qualcosa?

MODIFICARE:

Per chiarire in risposta a una risposta, la direzione della spedizione non è il problema che sto cercando. $scope.$emitinvia l'evento verso l'alto e $scope.$broadcast- verso il basso. Ma perché non usare sempre $rootScope.$broadcastper raggiungere tutti gli ascoltatori previsti?


Risposte:


1155

tl; dr (questo tl; dr è dalla risposta di @ sp00m di seguito)

$emitinvia un evento verso l'alto ... $broadcastinvia un evento verso il basso

Spiegazione dettagliata

$rootScope.$emitconsente solo agli altri $rootScopeascoltatori di catturarlo. Questo va bene quando non vuoi tutto$scope lo ottengano. Principalmente una comunicazione di alto livello. Pensa a come adulti che parlano tra loro in una stanza in modo che i bambini non possano sentirli.

$rootScope.$broadcastè un metodo che permette praticamente a tutto di ascoltarlo. Questo sarebbe l'equivalente dei genitori che urlano che la cena è pronta in modo che tutti in casa la sentano.

$scope.$emitè quando vuoi questo $scopee tutti i suoi genitori e $rootScopeascoltare l'evento. Questo è un bambino che si lamenta con i genitori a casa (ma non in un negozio di alimentari dove gli altri bambini possono ascoltare).

$scope.$broadcastè per $scopese stesso e i suoi figli. Questo è un bambino che sussurra ai suoi animali di peluche in modo che i loro genitori non possano sentire.


3
@NewDev Il motivo è perché spesso si hanno ripetizioni di ambiti nella pagina. Se si dispone di due o più ambiti che rappresentano diverse istanze di dati, ad esempio un elenco di record dei pazienti su una pagina, ciascuno con il proprio ambito, non funzionerà per trasmettere dalla radice un evento destinato solo a uno di questi ambiti. Evitare le $rootScopetrasmissioni ove possibile consente un migliore riutilizzo.
Tim Rogers,

4
Nulla di ciò che hai detto è sbagliato, ma un modo per generalizzare che $ emit scende dal documento agli ambiti figlio e $ emit sale al documento agli ambiti padre. Entrambi attiveranno tutti gli ascoltatori collegati all'ambito corrente.
Eric

123
L'esempio che hai usato è fantastico!
Assaf,

72
Wow! Anche i bambini possono capirlo! Incredibile :)
Navaneeth,

3
Esempio perfetto, adoro la spiegazione
Robin-Hoodie,

104

Non stanno facendo lo stesso lavoro: $emitinvia un evento verso l' alto attraverso la gerarchia dell'ambito, mentre $broadcastinvia un evento verso il basso a tutti gli ambiti figlio.


2
Sì, l'ho notato nella domanda (forse avrei potuto chiarire la direzione della spedizione). Ma ho anche notato che si tratta di una restrizione piuttosto arbitraria. Se riesco a raggiungere il mio "ascoltatore", perché non posso farlo sempre verso il basso $rootScope?
Nuovo Dev

Perché un'emissione $ non influirà sugli ambiti figlio o fratello di un ambito. Questi si limitano a mappare i tipi di propagazione degli eventi di javascript: acquisizione e bolle. $ broadcast è usato per catturare e $ emit è usato per gorgogliare. C'è un articolo quirksmode ora apparentemente antico che spiega abbastanza bene la differenza: quirksmode.org/js/events_order.html
Alan L.

77

Ho creato il seguente grafico dal seguente link: https://toddmotto.com/all-about-angulars-emit-broadcast-on-publish-subscribing/

Scope, rootScope, emit, broadcast

Come puoi vedere, $rootScope.$broadcastcolpisce molto più ascoltatori di $scope.$emit.

Inoltre, $scope.$emitl'effetto gorgogliante può essere annullato, mentre $rootScope.$broadcastnon è possibile.


24
Vedo molte frecce.
Mars Robertson,

4
@MichalStefanow Sono un fan delle risposte visive :)
Maria Ines Parnisari,

@mparnisari:. $ broadcast (nome, args) - Trasmette un evento attraverso $ scope di tutti i bambini. $ emit (name, args) - Emette un evento nella gerarchia $ scope a tutti i genitori, incluso $ rootScope
CodeMan,

19

inserisci qui la descrizione dell'immagine

$ scope. $ emit: questo metodo invia l'evento verso l'alto (da figlio a genitore)

inserisci qui la descrizione dell'immagine $ scope. $ broadcast: il metodo invia l'evento verso il basso (da genitore a figlio) a tutti i controllori figlio.

inserisci qui la descrizione dell'immagine $ scope. $ on: il metodo registra per ascoltare alcuni eventi. Tutti i controller che stanno ascoltando quell'evento ricevono una notifica della trasmissione o emettono in base al punto in cui si inseriscono nella gerarchia padre-figlio.

L'evento $ emit può essere annullato da qualsiasi $ scope che sta ascoltando l'evento.

$ On fornisce il metodo "stopPropagation". Chiamando questo metodo è possibile interrompere ulteriormente la propagazione dell'evento.

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

Nel caso di ambiti fratelli (gli ambiti che non si trovano nella gerarchia padre-figlio diretta), allora $ emit e $ broadcast non comunicheranno agli ambiti fratelli.

inserisci qui la descrizione dell'immagine

Per maggiori dettagli, consultare http://yogeshtutorials.blogspot.in/2015/12/event-based-communication-between-angularjs-controllers.html


Un link a una soluzione è il benvenuto, ma assicurati che la tua risposta sia utile senza di essa: aggiungi un contesto attorno al link in modo che i tuoi colleghi utenti abbiano qualche idea di cosa sia e perché sia ​​lì, quindi cita la parte più pertinente della pagina che ' re collegamento a nel caso in cui la pagina di destinazione non sia disponibile. Le risposte che sono poco più di un collegamento possono essere eliminate.
Baum mit Augen

L'obiettivo era fornire il plunker di lavoro, tuttavia, ho aggiunto qui la descrizione appropriata.
Yogesh,

3

@Eddie ha dato una risposta perfetta alla domanda posta. Ma vorrei attirare l'attenzione sull'uso di un approccio più efficiente di Pub / Sub.

Come suggerisce questa risposta,

L'approccio $ broadcast / $ on non è terribilmente efficiente in quanto trasmette a tutti gli ambiti (in una direzione o in entrambe le direzioni della gerarchia Scope). Mentre l'approccio Pub / Sub è molto più diretto. Solo gli abbonati ricevono gli eventi, quindi non andranno in tutti gli ambiti del sistema per farlo funzionare.

puoi usare angular-PubSubil modulo angolare. una volta aggiunto il PubSubmodulo alla dipendenza dell'app, è possibile utilizzare il PubSubservizio per iscriversi e annullare l'iscrizione a eventi / argomenti.

Abbonarsi facilmente:

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

});

Facile da pubblicare

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

Per annullare l'iscrizione, utilizzare PubSub.unsubscribe(sub);OR PubSub.unsubscribe('event-name');.

NOTA Non dimenticare di annullare l'iscrizione per evitare perdite di memoria.


2

Usa RxJS in un servizio

Che dire in una situazione in cui hai un servizio che detiene lo stato, ad esempio. Come posso inviare modifiche a quel servizio e altri componenti casuali sulla pagina essere consapevoli di tale modifica? Ultimamente ho avuto difficoltà ad affrontare questo problema

Crea un servizio con le estensioni RxJS per 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);
      }
  };
});

Quindi semplicemente iscriviti alle modifiche.

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

I clienti possono abbonarsi ai cambiamenti con DataService.subscribee i produttori possono spingere i cambiamenti con DataService.set.

La DEMO su PLNKR .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.