W mojej aplikacji mam usługę i18n, która zawiera następujący kod:
var i18nService = function() {
this.ensureLocaleIsLoaded = function() {
if( !this.existingPromise ) {
this.existingPromise = $q.defer();
var deferred = this.existingPromise;
var userLanguage = $( "body" ).data( "language" );
this.userLanguage = userLanguage;
console.log( "Loading locale '" + userLanguage + "' from server..." );
$http( { method:"get", url:"/i18n/" + userLanguage, cache:true } ).success( function( translations ) {
$rootScope.i18n = translations;
deferred.resolve( $rootScope.i18n );
} );
}
if( $rootScope.i18n ) {
this.existingPromise.resolve( $rootScope.i18n );
}
return this.existingPromise.promise;
};
Chodzi o to, że użytkownik dzwoniłby ensureLocaleIsLoaded
i czekał, aż obietnica zostanie rozwiązana. Ale biorąc pod uwagę, że celem tej funkcji jest tylko zapewnienie załadowania ustawień regionalnych, byłoby w porządku, gdyby użytkownik wywołał ją kilka razy.
Obecnie przechowuję tylko jedną obietnicę i rozwiązuję ją, jeśli użytkownik ponownie wywoła funkcję po pomyślnym pobraniu ustawień regionalnych z serwera.
Z tego, co wiem, działa to zgodnie z przeznaczeniem, ale zastanawiam się, czy jest to właściwe podejście.
javascript
angularjs
Der Hochstapler
źródło
źródło
Odpowiedzi:
Jak obecnie rozumiem obietnice, powinno to być w 100% w porządku. Jedyną rzeczą do zrozumienia jest to, że raz rozwiązany (lub odrzucony), to znaczy dla odroczonego obiektu - jest zrobiony.
Jeśli
then(...)
ponownie skorzystasz z obietnicy, powinieneś natychmiast uzyskać (pierwszy) rozstrzygnięty / odrzucony wynik.Dodatkowe wywołania do
resolve()
nie będą (nie powinny?) Mieć żadnego efektu. Nie jestem pewien, co się stanie, jeśli spróbujeszreject
odłożyć obiekt, który był wcześniejresolved
(nic nie podejrzewam).źródło
Spotkałem się z tym samym jakiś czas temu, rzeczywiście, obietnicę można spełnić tylko raz, kolejne próby nic nie dadzą (bez błędu, bez ostrzeżenia, bez
then
wezwania).Postanowiłem to obejść w ten sposób:
po prostu przekaż swoją funkcję jako wywołanie zwrotne i wywołuj ją tyle razy, ile chcesz! Mam nadzieję, że to ma sens.
źródło
getUsers
a następnie przywoływać.then()
ją tyle razy, ile chcesz. Nie ma potrzeby przekazywania oddzwonienia. Moim zdaniem jedną z zalet obietnic jest to, że nie musisz z góry określać wywołania zwrotnego..then
instrukcji. Jeśli chodzi o to, co jest warte, myślę, że jedynym sposobem na wielokrotne zwracanie danych do kontekstu wywołania jest użycie wywołań zwrotnych, a nie obietnic, ponieważ obietnice nie zostały zbudowane tak, aby działały w ten sposób.Jeśli chcesz zmienić zwracaną wartość obietnicy, po prostu zwróć nową wartość
then
i połącz ją następnąthen
/catch
na niejźródło
Nie ma jasnego sposobu na wielokrotne spełnianie obietnic, ponieważ skoro zostały rozwiązane, to już koniec. Lepszym podejściem jest tutaj użycie wzorca obserwowalnego przez obserwatora, na przykład napisałem następujący kod, który obserwuje zdarzenie klienta gniazda. Możesz rozszerzyć ten kod zgodnie ze swoimi potrzebami
źródło
Możesz napisać testy, aby potwierdzić zachowanie.
Wykonując następujący test, możesz to stwierdzić
Możesz również sprawdzić mój wpis na blogu, aby uzyskać szczegółowe informacje.
źródło
Powinieneś umieścić ng-if na swoim głównym wylocie ng-if i pokazać zamiast tego spinner ładujący. Po załadowaniu ustawień regionalnych wyświetlasz gniazdko i pozwalasz na renderowanie hierarchii komponentów. W ten sposób cała aplikacja może założyć, że ustawienia regionalne są załadowane i żadne kontrole nie są konieczne.
źródło