![]()
In AngularJS, $scope.$apply() is a method that forces Angular to run a digest cycle and update the bindings between the model (scope variables) and the view (HTML template). However, using $apply() incorrectly can lead to performance issues, excessive digest cycles, or errors like “$digest already in progress”.
What Does $scope.$apply() Do?
- It executes a function inside Angular’s context and triggers a digest cycle.
- It ensures that model changes made outside of AngularJS (e.g., in event listeners, timeouts, AJAX calls) are detected and reflected in the UI.
- It should be used only when necessary, as it can trigger performance issues if misused.
When Should You Use $scope.$apply()?
You should use $scope.$apply() when you modify AngularJS scope variables outside of Angular’s control, such as:
- DOM Event Listeners
- Native JavaScript Timeouts (
setTimeout,setInterval) - Third-Party Library Callbacks
- WebSocket and AJAX Calls Without
$httpService
Correct Usage of $scope.$apply()
1️⃣ Using $scope.$apply() in Event Listeners
Incorrect Way (Model Won’t Update)
document.getElementById("btn").addEventListener("click", function() {
$scope.message = "Button Clicked!"; // Angular does not detect this change
});
Correct Way (Using $apply())
document.getElementById("btn").addEventListener("click", function() {
$scope.$apply(function() {
$scope.message = "Button Clicked!";
});
});
Why?
- Since
addEventListeneris outside AngularJS,$apply()ensures the view updates properly.
2️⃣ Using $scope.$apply() in setTimeout()
Incorrect Way (UI Won’t Update)
setTimeout(function() {
$scope.message = "Updated after 2 seconds"; // Angular won't detect the change
}, 2000);
Correct Way (Using $apply())
setTimeout(function() {
$scope.$apply(function() {
$scope.message = "Updated after 2 seconds";
});
}, 2000);
Why?
setTimeoutis a native JavaScript function, so Angular does not automatically track changes.
3️⃣ Using $scope.$apply() in Third-Party Library Callbacks
Incorrect Way (No UI Update)
socket.on("message", function(data) {
$scope.chatMessage = data.text; // No automatic UI update
});
Correct Way (Using $apply())
socket.on("message", function(data) {
$scope.$apply(function() {
$scope.chatMessage = data.text;
});
});
Why?
- WebSocket events are outside Angular’s control, so
$apply()ensures updates.
4️⃣ Using $scope.$apply() with jQuery AJAX Calls
Incorrect Way (UI Won’t Update)
$.ajax({
url: "/api/data",
success: function(response) {
$scope.data = response; // Angular won’t detect this update
}
});
Correct Way (Using $apply())
$.ajax({
url: "/api/data",
success: function(response) {
$scope.$apply(function() {
$scope.data = response;
});
}
});
Why?
- jQuery operates outside of AngularJS, so changes need to be manually updated.
When NOT to Use $scope.$apply()
Inside AngularJS Services Like $http, $timeout, and $interval
These services already trigger a digest cycle, so using $apply() is unnecessary.
Correct Usage Without $apply()
$http.get("/api/data").then(function(response) {
$scope.data = response.data; // No need for $apply()
});
$timeout(function() {
$scope.message = "Updated!"; // No need for $apply()
}, 1000);
Why?
- Angular services already trigger digest cycles, so manually calling
$apply()can cause excessive digest cycles and slow performance.
Common Errors and How to Fix Them
1️⃣ Error: “$digest already in progress”
This happens when $apply() is called inside a function that is already being tracked by Angular.
Incorrect:
$scope.$apply(function() {
$scope.message = "Hello";
$scope.$apply(function() { // Nested $apply()
$scope.name = "Angular";
});
});
Fix: Use $scope.$evalAsync() Instead
$scope.$apply(function() {
$scope.message = "Hello";
$scope.$evalAsync(function() { // ✅ Use $evalAsync() inside an existing digest cycle
$scope.name = "Angular";
});
});
Why?
$evalAsync()schedules an update without triggering another digest cycle.
$scope.$apply() vs. $scope.$digest() – Key Differences
| Feature | $scope.$apply() | $scope.$digest() |
|---|---|---|
| Scope Level | Triggers a global digest cycle | Runs a digest cycle only in the current scope |
| Use Case | When updating the model from outside Angular | When updating data in the current scope manually |
| Performance | Can slow down performance if overused | More efficient, but does not affect child scopes |
| Example Usage | Third-party events, setTimeout, WebSocket updates | Fine-tuning scope changes when $apply() is too broad |
Use $scope.$digest() if you only need to update the current scope to improve performance.
