Подтвердить что ты не робот

Используйте Promise и службу вместе в Angular

Мой вопрос основан на в этом разделе в группе Angular Google.
Я хочу предоставить службу, которая хранит некоторые базовые данные, извлеченные из бэкэнд через $http, тогда мне нужно только один раз получить эти данные. например,

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
}]);

Проблема в том, что цепочка обещаний заканчивается в userProvider, но не в контроллере, поэтому пользователь undefined при первом использовании этого контроллера, поскольку данные не были возвращены.

Как я могу использовать такую ​​службу хранения и правильно вернуть данные? Спасибо!

4b9b3361

Ответ 1

Вы можете просто создать свое собственное обещание. Вот модифицированный код:

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 consistent across invocations
    if ( angular.isDefined( user ) ) return $q.when( user );

    // Otherwise, let 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()
  };
});

Обновление: Решение ниже от @yohairosen является отличным для многих обстоятельств, но не для всех. В некоторых случаях мы хотели бы только кэшировать успешный результат, как я это сделал. Если, например, отказ этого запроса указывает, что пользователю необходимо сначала войти в систему, мы не захотим следующего вызова (предположительно после входа в систему), чтобы доставить сбой кэширования. В тех случаях, когда метод не обязательно согласован с призывом к вызову при любых обстоятельствах, этот метод лучше; во всех остальных случаях решение @yohairosen проще и рекомендуется.

Ответ 2

Немного накладных расходов, чтобы создать свое собственное обещание, angular $http создает для вас все равно. То, что вы ищете, - это кеширование, а http может обрабатывать его для вас, передавая кеш: true для вызова службы.

Итак, вы можете просто сделать что-то вроде этого:

 module.factory("userProvider", function() {
   var getUser = function() {
   return $http.get(..., {cache:true}).then(function(data) {
       return data.user; 
   });

   return {
       getUser : getUser
   }
});