116

Tried to find some basic information for AngularJS $rootScope.$broadcast, But the AngularJS documentation doesn't help much. In easy words why do we use this?

Also, inside John Papa's Hot Towel template there is a custom function in the common module named $broadcast:

function $broadcast() {
    return $rootScope.$broadcast.apply($rootScope, arguments);
}

I did not understand what this is doing. So here are couple of basic questions:

1) What does $rootScope.$broadcast do?

2) What is the difference between $rootScope.$broadcast and $rootScope.$broadcast.apply?

Nexus23
  • 6,195
  • 9
  • 50
  • 67
  • 2
    https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/apply – Blackhole Jul 18 '14 at 17:44
  • http://mariuszprzydatek.com/2013/12/28/sharing-data-between-controllers-in-angularjs-pubsub-event-bus-example/ – Pankaj Parkar Jul 18 '14 at 18:16
  • `$rootScope.$broadcast.apply()` is used because if you want to pass the special `arguments` object to another function, you need to use `apply()` (as opposed to `call()`). In addition to @Blackhole's link to the MDN page on apply, you might also check out the entry on [`arguments`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments). – Scott Schupbach Sep 02 '16 at 19:46

5 Answers5

159

$rootScope basically functions as an event listener and dispatcher.

To answer the question of how it is used, it used in conjunction with rootScope.$on;

$rootScope.$broadcast("hi");

$rootScope.$on("hi", function(){
    //do something
});

However, it is a bad practice to use $rootScope as your own app's general event service, since you will quickly end up in a situation where every app depends on $rootScope, and you do not know what components are listening to what events.

The best practice is to create a service for each custom event you want to listen to or broadcast.

.service("hiEventService",function($rootScope) {
    this.broadcast = function() {$rootScope.$broadcast("hi")}
    this.listen = function(callback) {$rootScope.$on("hi",callback)}
})
Denison Luz
  • 3,575
  • 23
  • 25
Code Whisperer
  • 22,959
  • 20
  • 67
  • 85
  • 4
    Thanks @itcouldevenbeabout isn't this line calling the same logic of attaching an event to global $rootScope? function() {$rootScope.$broadcast("hi")}, which you mentioned is a bad practice? – Nexus23 Jul 20 '14 at 10:49
  • 11
    Using a service to make the broadcasts and also attach the listeners for a specific event avoids the situation where you're not sure who is listening. It becomes clear which components have the event service as a dependency – CoolTapes Nov 18 '14 at 17:30
  • @itcouldevenbeaboat but if you want to see where it is used you have to search for the service name, but without it you can search for it using just event name? It doesn't give anything more or I overlooked something? – tobi Mar 30 '15 at 06:59
  • Agreed with the assessment this suggestion appears to be a superficial wrapper. Why is this considered a best practice? Thanks. – Chris Camaratta May 08 '15 at 15:39
  • This makes refactoring and evolving the code easier. For example, if you wanted to change the event name (e.g. to avoid colliding with some 3rd-party code), or if you wanted to not depend on $rootScope, or if you wanted to add more sophisticated functionality, e.g. keeping track of listeners programmatically, or firing events to only some of them, or waiting for some asynchronous work... then you'd only have to change the service file, not all of its dependents. – Lawrence May 28 '15 at 02:36
  • 4
    Having just discovered the difference between $emit and $broadcast, I'd be inclined to say that it would be better to $emit the event - that way you the event polluting in the smallest possible set of scopes, (ideally the service would have it's own scope, but I don't think that's possible?) – Brondahl Jun 29 '15 at 13:19
  • @Brondahl, that is a great suggestion, and I second it. It would be better to use $emit in this particular example. – Jadiel de Armas Aug 02 '15 at 21:26
  • 3
    -1. I don't see, how isolation in a service is any better than simply broadcasting. Anyway, better use own private scope in the service. And better use $emit, and not $broadcast. Also your proposed service does not support event arguments. What's worse it doesn't support unsubscription; a mortal sin for $rootScope. – alpha-mouse Sep 28 '15 at 13:51
  • 2
    @alpha-mouse, There _is_ no private `scope` in a service. – adamdport Oct 29 '15 at 20:57
  • 4
    The lack of unsubscription ruins this answer for me. If you call `hiEventService.listen(callback)` from a controller, the listener will still exist even after the controller is destroyed. Memory leak! Binding to controller scope `$scope.$on("hi",callback)` comes with automatic cleanup. – adamdport Oct 29 '15 at 21:02
  • @adamdport one can be created by calling $rootScope.$new. But this doesn't matter much, there are greater problems with the proposed service anyway. – alpha-mouse Oct 29 '15 at 21:39
  • 1
    Your implementation will cause memory leaks as listeners are never unregistered. – Petr Peller May 17 '16 at 12:36
107
  1. What does $rootScope.$broadcast do?

    $rootScope.$broadcast is sending an event through the application scope. Any children scope of that app can catch it using a simple: $scope.$on().

    It is especially useful to send events when you want to reach a scope that is not a direct parent (A branch of a parent for example)

    !!! One thing to not do however is to use $rootScope.$on from a controller. $rootScope is the application, when your controller is destroyed that event listener will still exist, and when your controller will be created again, it will just pile up more event listeners. (So one broadcast will be caught multiple times). Use $scope.$on() instead, and the listeners will also get destroyed.

  2. What is the difference between $rootScope.$broadcast & $rootScope.$broadcast.apply?

    Sometimes you have to use apply(), especially when working with directives and other JS libraries. However since I don't know that code base, I wouldn't be able to tell if that's the case here.

A J A Y
  • 585
  • 1
  • 7
  • 22
user1412031
  • 1,086
  • 1
  • 8
  • 3
  • 12
    Great catch on the `$rootScope.$on` memory leak. This applies to the accepted answer too, as controllers are likely to call the `hiEventService` he created. – adamdport Oct 29 '15 at 21:18
  • What is an example where you would use `$broadcast` vs. `$broadcast.apply()` – guest Aug 05 '16 at 15:52
  • $rootScope.$broadcast sends the event to all listeners, not only listeners from children scopes. $scope.$broadcast limits the event to child scopes – Geert Bellemans Mar 22 '17 at 10:49
33

$rootScope.$broadcast is a convenient way to raise a "global" event which all child scopes can listen for. You only need to use $rootScope to broadcast the message, since all the descendant scopes can listen for it.

The root scope broadcasts the event:

$rootScope.$broadcast("myEvent");

Any child Scope can listen for the event:

$scope.$on("myEvent",function () {console.log('my event occurred');} );

Why we use $rootScope.$broadcast? You can use $watch to listen for variable changes and execute functions when the variable state changes. However, in some cases, you simply want to raise an event that other parts of the application can listen for, regardless of any change in scope variable state. This is when $broadcast is helpful.

Chukwuemeka
  • 342
  • 6
  • 11
James Lawruk
  • 30,112
  • 19
  • 130
  • 137
25

Passing data !!!

I wonder why no one mention that $broadcast accept a parameter where you can pass an Object

Example:

// the object to transfert
var obj = {
    status : 10
}

$rootScope.$broadcast('status_updated', obj);
$scope.$on('status_updated', function(event, obj){
    console.log(obj.status); // 10
})
Merlin
  • 4,907
  • 2
  • 33
  • 51
8

What does $rootScope.$broadcast do?

It broadcasts the message to respective listeners all over the angular app, a very powerful means to transfer messages to scopes at different hierarchical level(be it parent , child or siblings)

Similarly, we have $rootScope.$emit, the only difference is the former is also caught by $scope.$on while the latter is caught by only $rootScope.$on .

refer for examples :- http://toddmotto.com/all-about-angulars-emit-broadcast-on-publish-subscribing/

Prasad
  • 1,562
  • 5
  • 26
  • 40
Prashant K
  • 869
  • 9
  • 9