AngularJS provides the $q
service to handle asynchronous operations efficiently using Promises. The $q.defer()
method helps create and manage promises manually.
1. What is $q.defer()
?
$q.defer()
is a method in AngularJS that creates a deferred object, which can later be resolved or rejected based on the result of an asynchronous operation.
Why Use $q.defer()
?
✔ Better readability compared to callbacks
✔ Handles multiple async operations (e.g., API calls, timeouts)
✔ Chaining of promises for sequential execution
✔ Centralized error handling
2. Basic Usage of $q.defer()
Example: Simulating an Asynchronous Task
var app = angular.module("myApp", []);
app.controller("MainController", function ($scope, $q) {
function asyncOperation() {
var deferred = $q.defer(); // Create a deferred object
setTimeout(function () {
if (Math.random() > 0.5) {
deferred.resolve("Success: Data received!");
} else {
deferred.reject("Error: Something went wrong.");
}
}, 2000);
return deferred.promise; // Return the promise
}
$scope.getData = function () {
asyncOperation()
.then(function (result) {
$scope.message = result;
})
.catch(function (error) {
$scope.message = error;
});
};
});
🔹 How it Works?
deferred
object is created using$q.defer()
.resolve()
orreject()
is called after 2 seconds based on a random condition..then()
executes when resolved, and.catch()
executes when rejected.
3. Using $q.defer()
with HTTP Requests
Example: Handling API Calls Manually
app.service("DataService", function ($http, $q) {
this.getData = function () {
var deferred = $q.defer();
$http.get("https://jsonplaceholder.typicode.com/posts/1")
.then(function (response) {
deferred.resolve(response.data);
})
.catch(function (error) {
deferred.reject(error.statusText);
});
return deferred.promise;
};
});
app.controller("APIController", function ($scope, DataService) {
$scope.loadData = function () {
DataService.getData()
.then(function (data) {
$scope.post = data;
})
.catch(function (error) {
$scope.error = "Failed to load data: " + error;
});
};
});
🔹 Why Use $q.defer()
Here?
- Allows custom logic before resolving/rejecting the HTTP response.
- You can modify the response before returning.
- Ensures a consistent API for async functions.
4. Combining Multiple Promises with $q.all()
Sometimes, you need to execute multiple async calls in parallel and wait for all of them to complete before proceeding.
Example: Fetching Multiple API Data
app.controller("MultiAPIController", function ($scope, $q, $http) {
function getUser() {
return $http.get("https://jsonplaceholder.typicode.com/users/1");
}
function getPosts() {
return $http.get("https://jsonplaceholder.typicode.com/posts?userId=1");
}
$scope.loadData = function () {
$q.all([getUser(), getPosts()])
.then(function (results) {
$scope.user = results[0].data; // First API response
$scope.posts = results[1].data; // Second API response
})
.catch(function (error) {
$scope.error = "Error loading data: " + error.statusText;
});
};
});
🔹 Why Use $q.all()
?
- Waits until all promises are resolved.
- Returns an array of results.
- Fails if any one of the promises is rejected.
5. Alternative: Using $q.when()
If you already have a value or a promise, you can wrap it in a promise using $q.when()
.
Example
app.controller("WhenExampleController", function ($scope, $q) {
function getStaticData() {
return $q.when("This is static data, wrapped in a promise.");
}
$scope.loadData = function () {
getStaticData().then(function (data) {
$scope.message = data;
});
};
});
🔹 Why Use $q.when()
?
- Converts a normal value into a promise.
- Ensures consistent promise-based return values.
6. Difference Between $q.defer()
and $http
Promises
Feature | $q.defer() | $http Promise |
---|---|---|
Manual Handling | Required | Not needed (auto-resolves) |
Use Case | Complex async logic | Simple API calls |
Chaining | Supported | Supported |
Error Handling | Customizable | Built-in |
Use $q.defer()
when:
- You need to manually trigger resolution of a promise.
- You have custom async workflows beyond just HTTP calls.
- You want fine-grained control over promise execution.