$q allows creating and chaining custom promises, suitable for handling complex async tasks. By using $q.defer(), we can manage promise resolution or rejection and streamline complex async workflows with then(), all(), and catch() for handling errors.
function getData() {
var deferred = $q.defer();
$http.get('/api/data').then(response => {
deferred.resolve(response.data);
}, error => {
deferred.reject(error);
});
return deferred.promise;
}