How would you implement custom $q promises to manage complex asynchronous tasks?

$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;
}