2013-01-15 22 views
20

Moje pytanie jest oparte na this topic w Angular Google group.
Chcę zapewnić usługę, która przechowuje podstawowe dane pobrane z backendu za pomocą $ http, a następnie wystarczy pobrać te dane tylko raz. jak,Użyj obietnicy i usługi razem w Angular

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

Problem polega na tym, że łańcuch obietnica kończy się userProvider ale nie w sterowniku, dzięki czemu użytkownik jest niezdefiniowana po raz pierwszy używam tego kontrolera, ponieważ dane nie zostały zwrócone.

Jak mogę korzystać z takiej usługi pamięci masowej i poprawnie zwracać dane? Dzięki!

Odpowiedz

18

Możesz po prostu stworzyć swoją własną obietnicę. Oto zmodyfikowany kod:

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

Aktualizacja: Poniższa rozwiązanie przez @yohairosen jest doskonałym jeden dla wielu okolicznościach, ale nie dla wszystkich. W pewnych okolicznościach chcielibyśmy tylko buforować wyniki powodzeniem, tak jak to zrobiłem tutaj. Jeśli, na przykład, niepowodzenie tego żądania wskazuje, że użytkownik musi się najpierw zalogować, nie chcemy następnego połączenia (prawdopodobnie po zalogowaniu), aby dostarczyć awarię z pamięci podręcznej. W przypadkach, gdy metoda nie musi być spójna z wezwaniem do połączenia we wszystkich okolicznościach, ta metoda jest lepsza; we wszystkich innych przypadkach rozwiązanie @ yohairosen jest prostsze i zalecane.

+0

Dzięki Josh, to działa! – Edward

+2

Działa świetnie. Jedyne, czego może brakować, to coś, co zapobiega dodatkowym zewnętrznym połączeniom, podczas gdy pierwsze połączenie pobiera dane. – keyser

17

To trochę więcej niż potrzeba, by stworzyć własną obietnicę, a $ HTTP HTTP na końcu tworzy taką dla Ciebie. To, czego szukasz, to cachowanie i http może zająć się dla ciebie przekazując cache: true do zgłoszenia serwisowego.

więc można po prostu zrobić coś takiego:

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

    return { 
     getUser : getUser 
    } 
}); 
Powiązane problemy