AngularJS Angular promises with $q service Using angular promises with $q service


Example

$q is a built-in service which helps in executing asynchronous functions and using their return values(or exception) when they are finished with processing.

$q is integrated with the $rootScope.Scope model observation mechanism, which means faster propagation of resolution or rejection into your models and avoiding unnecessary browser repaints, which would result in flickering UI.

In our example, we call our factory getMyData, which return a promise object. If the object is resolved, it returns a random number. If it is rejected, it return a rejection with an error message after 2 seconds.

In Angular factory

function getMyData($timeout, $q) {
  return function() {
    // simulated async function
    var promise = $timeout(function() {
      if(Math.round(Math.random())) {
        return 'data received!'
      } else {
        return $q.reject('oh no an error! try again')
      }
    }, 2000);
    return promise;
  }
}

Using Promises on call

angular.module('app', [])
.factory('getMyData', getMyData)
.run(function(getData) {
  var promise = getData()
    .then(function(string) {
      console.log(string)
    }, function(error) {
      console.error(error)
    })
    .finally(function() {
      console.log('Finished at:', new Date())
    })
})

To use promises, inject $q as dependency. Here we injected $q in getMyData factory.

var defer = $q.defer();

A new instance of deferred is constructed by calling $q.defer()

A deferred object is simply an object that exposes a promise as well as the associated methods for resolving that promise. It is constructed using the $q.deferred() function and exposes three main methods: resolve(), reject(), and notify().

  • resolve(value) – resolves the derived promise with the value.
  • reject(reason) – rejects the derived promise with the reason.
  • notify(value) - provides updates on the status of the promise's execution. This may be called multiple times before the promise is either resolved or rejected.

Properties

The associated promise object is accessed via the promise property. promise – {Promise} – promise object associated with this deferred.

A new promise instance is created when a deferred instance is created and can be retrieved by calling deferred.promise.

The purpose of the promise object is to allow for interested parties to get access to the result of the deferred task when it completes.

Promise Methods -

  • then(successCallback, [errorCallback], [notifyCallback]) – Regardless of when the promise was or will be resolved or rejected, then calls one of the success or error callbacks asynchronously as soon as the result is available. The callbacks are called with a single argument: the result or rejection reason. Additionally, the notify callback may be called zero or more times to provide a progress indication, before the promise is resolved or rejected.

  • catch(errorCallback) – shorthand for promise.then(null, errorCallback)

  • finally(callback, notifyCallback) – allows you to observe either the fulfillment or rejection of a promise, but to do so without modifying the final value.

One of the most powerful features of promises is the ability to chain them together. This allows the data to flow through the chain and be manipulated and mutated at each step. This is demonstrated with the following example:

Example 1:

// Creates a promise that when resolved, returns 4.
function getNumbers() {

  var promise = $timeout(function() {
    return 4;
  }, 1000);
  
  return promise;
}

// Resolve getNumbers() and chain subsequent then() calls to decrement
// initial number from 4 to 0 and then output a string.
getNumbers()
  .then(function(num) {
      // 4
      console.log(num);
      return --num;
  })
  .then(function (num) {
      // 3
      console.log(num);
      return --num;
  })
   .then(function (num) {
      // 2
      console.log(num);
      return --num;
  })
  .then(function (num) {
      // 1
      console.log(num);
      return --num;
  })
  .then(function (num) {
      // 0
      console.log(num);
      return 'And we are done!';
  })
  .then(function (text) {
      // "And we are done!"
      console.log(text);        
  });