The number of subscribers grows every time $rootscope.$on is used

I currently have an Angular controller that is quite simple:

angular.controller('appCtrl', function ($scope, $rootScope) {
    $rootscope.$on('channel.message', function () {
      // do something here
    }
}); 

In addition, I have a sidebar on my webpage that directs me to a view associated with the mentioned controller.

The problem arises when each time I click on a link, Angular creates a new instance of the controller. While this is acceptable, I've noticed that the number of subscribers for my 'channel.message' event is continually increasing, which is not ideal.

I am aware that each piece of code simply adds another callback to the queue but I would like to find a way to only have a single subscriber. What are the recommended best practices in this scenario?

Additionally, I'm familiar with using $scope.$on but it's not suitable due to performance implications and the architecture design of the application itself.

Answer №1

Consider implementing a named function to call your event handler, which will execute it and then clean it up. Here is an example (also, ensure that $rootscope is properly spelled as $rootScope):

angular.controller('appCtrl', function ($scope, $rootScope) {
    var cleanUp = $rootScope.$on('channel.message', function () {
        // carry out tasks here
    };

    cleanUp();
});

I encountered a similar issue (with multiple callbacks being added to the queue), and the above method resolved it for me.


On a side note, I recommend formatting your controller in this way:

angular.controller('appCtrl', ['$scope','$rootScope', function($scope, $rootScope) {

}]);

Answer №2

As pointed out by @JoshBeam, the $rootScope.$on() method returns a function that can be used to deregister your listener. Here is an example:

var cleanUp = $rootscope.$on('channel.message', function () {
   // do stuff here
}

The next question is when to trigger this cleanup. Typically, you would want to deregister the listener when the controller is destroyed. Angular provides a convenient way to do this by firing a $destroy event just before tearing down a scope.

$scope.$on('$destroy', function() {
  cleanUp();
};

It's important to note that we are listening for the $destroy event on the $scope (not on $rootScope) in order to capture when the controller is being torn down. Your regular listener can still remain attached to $rootScope.

This pattern is also useful for preventing memory leaks, even if you don't have multiple listeners to worry about.

Answer №3

In my opinion, it would be beneficial to implement an $onRootScope function, which I have detailed in this response:

How can controllers effectively communicate in AngularJS?

This method simplifies the process by handling event handler deregistration automatically, and its usage is straightforward:

$scope.$onRootScope('barEvent', function(){})

Furthermore, it is worth mentioning that recent updates to angular have mitigated concerns regarding performance impacts of broadcasted events.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Verify whether a pop-up window has been opened

Situation: Greetings, I provide a sensitive service to my clients. However, some of them are generating advertisement popups (using JavaScript) on their websites where my service is integrated, causing issues for us. My service involves a .js file hosted ...

CSS Class ID selection for selectpicker

I have two classes: selectpicker with different IDs: selected_Test_Platforms and selected_SIL_relevant I am trying to assign a preselection from an array called "availableTestPlatforms" to the selected_Test_Platforms. Currently, when I use the selector $( ...

Is it possible to identify the form triggering the ajax call within a callback function?

There are multiple forms on my website that share the same structure and classes. The objective is to submit form data to the server using the POST method, and display an error message if any issues arise. Here's how the HTML code for the forms look ...

How can I resolve the vertical adjustment issue of Bootstrap 5 input group on mobile devices?

My current issue involves using Bootstrap 5.2.3 to create an input group that displays a set of spans with the ".input-group-text" class alongside inputs with the ".form-control" class. While this setup works well on a computer screen, it does not adjust c ...

At what point are DOMs erased from memory?

Recently, I've been working on an application that involves continuous creation and removal of DOM elements. One thing I noticed is that the process memory for the browser tab keeps increasing even though the javascript heap memory remains steady. To ...

Creating a Discord Bot: Building an Embed Table/List with Segmented Sections

Currently in the process of learning Javascript and venturing into discord.js, I'm fully aware that the code I am working with is not up to par and requires some serious refinements. The main objective here is to split up the arguments of a command a ...

"Easily toggle the visibility of values in checkboxes and organize them into groups with the power of JavaScript

Hey there! I am currently working on a project that involves grouping checkboxes and hiding/unhiding their content based on user interaction. Essentially, when the page first loads, the "All CARS" checkbox will be checked by default. If I then check the "C ...

Guide to Implementing i18n-iso-countries Library in React

I am currently developing a React application and attempting to utilize the i18n-iso-countries package to retrieve a countries object in English where keys represent iso codes and values represent country names. This process is straightforward in Node.js, ...

Using a set formatter in jqGrid within a personalized formatter

Can I incorporate a predefined formatter into a custom formatter? Here is an example using the colModel: colModel: [ ... { name: 'col1', formatter: myFormatter } ... ] Below is the custom formatter function: function myFormatter(cellVal ...

Seeking a quick conversion method for transforming x or x[] into x[] in a single line of code

Is there a concise TypeScript one-liner that can replace the arrayOrMemberToArray function below? function arrayOrMemberToArray<T>(input: T | T[]): T[] { if(Arrary.isArray(input)) return input return [input] } Trying to cram this logic into a te ...

Creating an object key using a passed literal argument in TypeScript

Can the following scenario be achieved? Given an argument, how can we identify the object key and access it? Any potential solutions? async function checkKey(arg:'key1'|'key2'){ // fetchResult returns an object with either {key1:&apo ...

Typescript is experiencing an error due to the use of attr("disabled", false) causing a disruption

Within my ts file, I'm using the code snippet below: $('input[type=hidden]').attr("disabled", false); The code functions as intended, however, an error persists: Argument of type 'false' is not assignable to parameter of typ ...

Ways to retrieve the current state within a function after invoking the setState method

I'm currently working on a function to store the blogPost object in a document within my Firestore database. The process I have in mind is as follows: Click on the SAVE button and initiate the savePost() function The savePost() function should then ...

Hiding Modal Box Upon User Login: A Step-by-Step Guide

After a user clicks the login button in my navigation, a modal box pops up. However, once the user logs in, the modal box does not disappear. How can I hide or remove the modal box when users click on the login button? This code snippet is from Home.vue: ...

Struggling to get the knockout js remove function to function properly within a nested table structure

I've been encountering issues while trying to eliminate the formulation elements with the 'Delete comp' link. I can't seem to figure out why it's not functioning as expected. Moreover, the 'Add another composition' link o ...

Sending a string data from client to a MongoDB database using Express.js and Node.js with the help of Sails framework

Need help with sending a string from client to mongoDB using Sails The "val" variable represents a string sent in real time from the client to the server database POST Form( is using HTML the best approach here? ) <!DOCTYPE html> <html> < ...

Changing the Javascript Date Object into JSON date format

I'm in the process of converting a timestamp generated by var now = new Date().getTime(); which results in the timestamp 1349916512100. I am looking to format the date as \/Date(1349916512100)\/ in order to incorporate it into a JSON st ...

Having issues with images not loading and receiving a 401 error with the API while using Vite in a production build

While working on my React project with Vite, I've encountered a few challenges during the production build process. Everything seems to be running smoothly when I use npm run dev, but when I try to build the project using npm run build and then previ ...

React Native application fails to return any values from an asynchronous operation in App function

Completely new to React Native, this is my first attempt at coding. I'm struggling with returning jsx from my App() function due to an asynchronous operation within it. Here's the code that I believe clearly demonstrates my issue: import React fr ...

Unable to showcase Angular model in an alternative view

I'm currently working on a sample application where I need to display my model in one view and allow editing in another. Here's the controller code I'm using: var app = angular.module('plunker', ['ngRoute']); app.contro ...