← all articles

Promises and the 'resolve' property in AngularJS

Tamas Piros | 1 May 2016 | AngularJS

Let’s have a look at a use-case for this. Let’s imagine that we’re building a user portal that requires someone to authenticate. We are going to have a mockup version of this and simply write a function that waits for 5 seconds and ‘logs in’ a user (in other words, we’ll only create a user variable (resolve a promise) after 5 seconds) We can utilise promises using $q in angular which is an implementation of the based on Kris Kowalski’s q library.

The code

Let’s work with this very simple HTML code (ommitting the actual setup for the ng-app directive):

<a href="#/yar">Click here to see the Resolve property in action</a>

‘yar’ (Yet Another Route) is a route that will be invoked when we click this link. Let’s have a look at the Angular code that displays us this route:

(function() {
 'use strict';
 angular
   .module('myApp', ['ngRoute'])
   .config(config)
   .controller('MainCtrl', MainCtrl)
   .controller('YarCtrl', YarCtrl)
   .factory('YarFactory', YarFactory);

 function config($routeProvider) {
   $routeProvider
     .when('/', {
       templateUrl: 'main.html',
       controller: 'MainCtrl',
       controllerAs: 'vm'
     })
     .when('/yar', {
       templateUrl: 'yar.html',
       controller: 'YarCtrl',
       controllerAs: 'vm'
     });
 }
 })();

And this is the code for the controller & factory:

YarFactory.$inject = ['$q', '$timeout'];
 function YarFactory($q, $timeout) {
   return {
     timeoutFunction: timeoutFunction
   };

   function timeoutFunction() {
     var deferred = $q.defer();

     $timeout(function() {
       var user = 'Tamas';
       deferred.resolve(user);
     }, 5000);

     return deferred.promise;
   }
 }

 YarCtrl.$inject = ['YarFactory'];
 function YarCtrl(YarFactory) {
   var vm = this;
   YarFactory.timeoutFunction().then(function(user) {
     vm.user = user
   });
 }

As mentioned earlier we are creating a new promise using $q and wait 5 seconds using $timeout to resolve the promise.

Adding the resolve property

Now, if you load the /yar route, you’ll notice that the HTML page is generated however the username appears after 5 seconds. This is not an ideal behaviour. Wouldn’t it be better if the route would only load then the username is available? Luckily there’s a special property for AngularJS routes that we can use, called resolve - let's take a look at this now:

.when('/yar', {
   templateUrl: 'yar.html',
   controller: 'YarCtrl',
   controllerAs: 'vm',
   resolve: {
     user: function(YarFactory) {
       return YarFactory.timeoutFunction();
     }
   }
 });

This tells the route to only load when the timeoutFunction resolved. We need to also modify the Controller slight as we no longer need to inject the Factory, instead we can reference the ‘user’ property from the resolve object, and we don’t need to call the timeoutFunction() method again:

 YarCtrl.$inject = ['user']
 function YarCtrl(user) {
   var vm = this;
   vm.user = user;
 }

If you navigate to the /yar route, you’ll see nothing for 5 seconds, and once the promise has been resolved, the route loads which is exactly the behaviour that we wanted to achieve. Now imagine that you have your own factory that goes out to a webservice - using the resolve property you can make sure that the particular route only loads when all the data has arrived from the webservice.

Free email mini-course on
Full Stack development

Sign up now to receive a free email mini-course covering the MEAN stack and more. Also be the first to know when we release new courses and videos.