How to avoid memory leaks in AngularJS?

Loading

Memory leaks in AngularJS occur when references to objects persist even after they are no longer needed. This can degrade application performance over time. Below are the best practices to avoid memory leaks in AngularJS.


1. Use $scope.$destroy() When Removing DOM Elements

When a scope is no longer needed, manually destroy it using $destroy() to prevent memory leaks.

Example:

$scope.$on("$destroy", function() {
console.log("Scope destroyed!");
});

This ensures that when a component or controller is removed, AngularJS cleans up the memory.


2. Unbind Event Listeners ($on)

If you use $scope.$on() for event handling, always unbind it in the $destroy method.

Example:

var eventListener = $scope.$on("customEvent", function(event, data) {
console.log("Event received:", data);
});

// Unbind when scope is destroyed
$scope.$on("$destroy", function() {
eventListener();
});

This prevents event handlers from accumulating and causing memory bloat.


3. Avoid Using jQuery Directly

If you must use jQuery, always clean up event listeners.

Bad Practice:

$(window).on("resize", function() {
console.log("Window resized");
});

Good Practice:

var resizeHandler = function() {
console.log("Window resized");
};

$(window).on("resize", resizeHandler);

$scope.$on("$destroy", function() {
$(window).off("resize", resizeHandler);
});

This ensures that the event listener is removed when the scope is destroyed.


4. Use One-Time Bindings (::) Where Possible

If data doesn’t change frequently, use one-time binding to reduce watchers.

Example:

<p>{{::user.name}}</p>

This ensures AngularJS stops watching user.name after the first evaluation, reducing memory usage.


5. Avoid Global Variables

Never store data globally, as it prevents garbage collection.

Bad Practice:

window.userList = [];

Good Practice:

Use $scope or services for data management.


6. Remove DOM Elements Manually

If you dynamically create DOM elements, remove them when they are no longer needed.

Example:

var element = angular.element("<div>Test</div>");
angular.element(document.body).append(element);

$scope.$on("$destroy", function() {
element.remove();
});

7. Limit $watch Usage

Too many $watch statements slow down the digest cycle.

Bad Practice:

$scope.$watch("data", function(newValue, oldValue) {
console.log("Data changed");
});

Good Practice:

Use $watch only when necessary or replace it with $watchCollection.

$scope.$watchCollection("items", function(newItems) {
console.log("Items changed");
});

8. Optimize $timeout and $interval Usage

Always cancel $timeout and $interval when they are no longer needed.

Example:

var timer = $timeout(function() {
console.log("Task executed");
}, 5000);

$scope.$on("$destroy", function() {
$timeout.cancel(timer);
});

For $interval, follow the same approach:

var interval = $interval(function() {
console.log("Repeating task");
}, 1000);

$scope.$on("$destroy", function() {
$interval.cancel(interval);
});

9. Clean Up Services

If a service holds persistent references, clean them up when they are no longer needed.

Example:

app.factory("DataService", function() {
var data = {};

return {
set: function(key, value) {
data[key] = value;
},
get: function(key) {
return data[key];
},
clear: function() {
data = {};
}
};
});

Call clear() when the service is no longer needed.


10. Use ng-if Instead of ng-show/ng-hide

ng-show and ng-hide only toggle visibility, but ng-if removes the element from the DOM, freeing memory.

Example:

<!-- Better than ng-show -->
<div ng-if="showElement">
<p>This element is added and removed dynamically.</p>
</div>

Leave a Reply

Your email address will not be published. Required fields are marked *