Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use Promise and service together in Angular

Tags:

My question is based on this topic in Angular Google group.
I want to provide a service which stores some basic data retrieved from the backend via $http, then I only need to fetch those data once. like,

var load = function() {
   return $http.get(...).then(function(data) {
       return data.user; 
   });
};

module.factory("userProvider", function() {
    var user;
    var getUser = function() {
        if(!user) {
            load().then(function(data) {
               user = data;
           });
        }
        return user;
    };
    return {
        getUser : getUser
    }
});

module.controller("UserController", ["userProvider", function UserController("userProvider") {
    var user = userProvider.getUser();
    // do something with user
}]);

The problem is that the promise chain ends in userProvider but not in controller, so the user is undefined the first time I use this controller since the data has not been returned.

How can I use such a storage service and return the data correctly? Thanks!

like image 554
Edward Avatar asked Jan 15 '13 07:01

Edward


People also ask

Which is better Promise or observable?

Often Observable is preferred over Promise because it provides the features of Promise and more. With Observable it doesn't matter if you want to handle 0, 1, or multiple events. You can utilize the same API in each case. Observable also has the advantage over Promise to be cancellable.

How do you write a Promise in angular 8?

This an example of a simple promise object that returns I promise to return this after 1 second! var promise = new Promise(function(resolve, reject) { setTimeout(function() { resolve('I promise to return this after 1 second!' ); }, 1000); }); promise. then(function(value) { console.


1 Answers

You can just create your own promise. Here is the modified code:

module.factory( "userProvider", function( $q ) {
  // A place to hold the user so we only need fetch it once.
  var user;

  function getUser() {
    // If we've already cached it, return that one.
    // But return a promise version so it's consistent across invocations
    if ( angular.isDefined( user ) ) return $q.when( user );

    // Otherwise, let's get it the first time and save it for later.
    return whateverFunctionGetsTheUserTheFirstTime()
    .then( function( data ) {
      user = data;
      return user;
    });
  };

  // The public API
  return {
    getUser: getUser()
  };
});

Update: The solution below by @yohairosen is a great one for many circumstances, but not for all. In some circumstances, we would only want to cache the successful result, as I have done here. If, for example, a failure of this request indicates the user needs to log in first, we would not want the next call (presumably after logging in) to deliver the cached failure. In cases where the method isn't necessarily consistent from call-to-call in all circumstances, this method is better; in all other cases, @yohairosen's solution is simpler and recommended.

like image 126
Josh David Miller Avatar answered Sep 19 '22 13:09

Josh David Miller