2

I created a JSFiddle to illustrate my situation: http://jsfiddle.net/hLv27/

I have a set of directives that should be independent one from the other but update depending on the data provided by an attribute (topics). I can exemplify this by using the same directive multiple times:

<my-directive topics="main.topicList"></my-directive>
<my-directive topics="main.staticTopicList"></my-directive>
<my-directive topics="main.topicList" update-on="some.event"></my-directive>

Each directive fetches its data from the server, depending on the topics:

  • in the first case, I would use a $watch, observe the topics array, and fetch new data accordingly;

    $scope.$watch("topics", function (theTopics) {
        $scope.fetchData(theTopics);
    });
    
  • in the second case, the directive is initialised with a fixed array and I do not need to update it afterwards;

  • in the third case, I would add to each directive a update-on string corresponding to a broadcast that gets fired when the topics array changes.

    if ($scope.updateOn) {
        $scope.$on($scope.updateOn, function (ev, tags) {
            $scope.fetchData(tags);
        });
    }
    

The question is: would it be better to use $watch or $broadcast?

Addendum: is there a better way to create similar directives? (e.g. without having to watch or broadcast)

fusio
  • 3,595
  • 6
  • 33
  • 47
  • I would personally go for broadcast http://stackoverflow.com/questions/19616520/what-is-cheaper-performance-wise-broadcast-or-watch – David Bohunek Jul 28 '14 at 15:21
  • "One primitive comparison by cycle is nothing.", `fetchData` is called only when the array changes (`topics` has max length = 3) – fusio Jul 28 '14 at 15:24
  • Is the `topicList` will be initialized once and no further updates after that or it can be changed at any time? – runTarm Jul 28 '14 at 16:52
  • changes depending in the selected topics from a list (max 3) – fusio Jul 28 '14 at 16:58

1 Answers1

1

It would be much more efficient to use $broadcast. (Actually, $emit.)

What is better is an open question.

$watch is not very smart - it has to do a lot of work to determine whether something has changed. (Same story with $watchCollection.) "We" (the AngularJS community) use it because we've decided that the trade-offs are worth it. In most cases you don't have to do it very often, it's very accurate, and it's very easy to understand. It adheres to almost all of the principles of the AngularJS "world". In a completely modular world it's a great way to solve the problem... usually.

On the other hand, when you know for sure your data has been changed, $watch just asks AngularJS to turn around and guess at (well, work hard to calculate) this same fact you already know. Using a message broadcast is much more efficient - Angular only has to iterate through a small collection of listeners. It doesn't have to do any object/property-based typing or recursion through deep objects and collections. You're basically doing this work for it.

If you do that, consider $emit instead of $broadcast. In a true pub/sub there isn't much advantage to having those messages "bubble down" to each scope, and that's costly - enough to kill the advantage you just won in the first place. $rootScope.$emit() will keep those messages at a single level, and you can use $rootScope.$on() to listen for them. This will iterate through a single small collection of listeners for this event name, and it's done - no extra work required.

Ultimately, deciding what is "better" comes back to you. If you want efficiency, a message-based model is almost a perfect fit. If you want the elegance of a watcher, you might want a different option.

Chad Robinson
  • 4,575
  • 22
  • 27
  • Ok, I would say the directive watching its own parameters is "better" than it listening to some external message. So, the question here is how much more efficient are messages in this case? The `topics` array is very simple, it may contain at most 3 strings. The REST operation should not take much time (not that much data), and I suspect there is no difference between using `watch` or `on` which such service.. – fusio Jul 28 '14 at 16:50
  • The problems with micro-benchmarks are legendary, and this is right on the edge of that. With such a simple use-case, the theory is you should use whatever pattern you and any other devs who may need to maintain this code prefer. – Chad Robinson Jul 28 '14 at 17:02
  • For the `consider $emit instead of $broadcast`, just want to point out that the difference in performance has greatly reduced by this [fix](https://github.com/angular/angular.js/commit/80e7a4558490f7ffd33d142844b9153a5ed00e86) already in angular 1.2.7. Also see a new benchmark at this [post](http://stackoverflow.com/questions/11252780/whats-the-correct-way-to-communicate-between-controllers-in-angularjs/19498009#19498009). – runTarm Jul 28 '14 at 17:14