2013-07-26 10 views
78

Rozumiem, że zazwyczaj wystarczy dołączyć kod kontynuacji z zachowaniem połączenia i łańcucha o wartości then() podczas korzystania z obietnic.

Jednak chcę uruchomić asynchroniczne wywołanie z obietnicą, a następnie osobno rozpocząć 3-sekundową $timeout(), więc mogę wykonać akcję interfejsu użytkownika, TYLKO JEŚLI oryginalna obietnica jeszcze się nie zakończyła. (Przewiduję, że będzie to miało miejsce tylko w przypadku powolnych połączeń, urządzeń mobilnych w sieci 3G itd.).

Czy mogę spełnić obietnicę, czy jest ona kompletna, czy nie, bez blokowania lub oczekiwania?

+2

Otworzyłem problem w tym kanciastym i dostałem pomocną odpowiedź https://github.com/angular/angular.js/issues/8307#issuecomment-49903373 – derekdreery

+0

możliwy duplikat http://stackoverflow.com/questions/27039771/q-js-is-it-possible-to-know-if-a-promise-has-resolved-rejected-or-not – mvermand

Odpowiedz

36

Uważam, że najlepszą opcją, jaka jest, (bez modyfikowania źródła Angular i wysyłania żądania ściągnięcia) jest zachowanie lokalnej flagi, jeśli obietnica została rozwiązana. Zresetuj go za każdym razem, gdy ustawisz obietnicę, którą jesteś zainteresowany, i oznaczysz ją jako kompletną w numerze then() dla oryginalnej obietnicy. W polu $timeoutthen() sprawdź flagę, aby dowiedzieć się, czy pierwotna obietnica została rozwiązana, czy nie.

coś takiego:

var promiseCompleted = false; 
promise.then(function(){promiseCompleted=true;}) 
$timeout(...).then(function(){if(!promiseCompleted)doStuff()}) 

realizacja Kris Kowal obejmuje inne sposoby na sprawdzenie stanu obietnicy ale wydaje się wdrożenie kątowej dotyczącą $q niestety nie obejmuje tych.

+7

Byłoby lepiej użyć .finally() tutaj. Powyższy kod zaznaczy tylko flagę promiseCompleted na true, jeśli została pomyślnie rozstrzygnięta. –

+0

Dobra sprawa, w końcu jest prawdopodobnie lepsza. – shaunhusain

0

Nie znam dokładnego scenariusza, ale bardziej typowe jest ustawienie limitu czasu natychmiast po wywołaniu asynchronicznym (i wygenerowaniu obietnicy).

Podanie instrukcji jest w tym samym wątku zdarzeń co wywołanie asynchroniczne, więc nie musisz martwić się o możliwość wystąpienia efektu wyścigu. Ponieważ javascript jest ściśle pojedynczy, obietnice zwrotne od .then() gwarantują uruchamianie w wątku późniejszego zdarzenia.

+0

Następnie twój kod zostanie przerwany, gdy przeglądarki zaczną implementować asynchroniczne javascript, takie jak 'node'. –

8

To nie wydaje się możliwe, jak już wspomniałem @shaunhusain. Ale może to nie jest konieczne:

// shows stuff from 3s ahead to promise completetion, 
// or does and undoes it in one step if promise completes before 
$q.all(promise, $timeout(doStuff, 3000)).then(undoStuff); 

czy może lepiej:

var tooSlow = $timeout(doStuff, 3000); 
promise.always(tooSlow.cancel); 
1

miałem podobny problem, gdy trzeba sprawdzić, czy powrócił obietnica. Ponieważ funkcja AngularJS $watch zarejestruje zmianę podczas renderowania strony, nawet jeśli zarówno nowa jak i stara wartość są niezdefiniowane, muszę sprawdzić, czy istnieją jakieś dane, które warto przechowywać w moim zewnętrznym modelu.

Jest zdecydowanie hack ale zrobić to:

$scope.$watch('userSelection', function() { 
    if(promiseObject.hasOwnProperty("$$v"){ 
    userExportableState.selection = $scope.userSelection; 
    } 
}; 

wiem, że $$v jest zmienną wewnętrzne stosowane przez angularjs, ale to było dość wiarygodne jako wskaźnik jest rozwiązany obietnica dla nas. Kto wie, co się stanie, gdy uaktualnimy do AngularJS 1.2: -/nie widzę żadnej wzmianki o ulepszeniach $q w dokumentach 1.2, ale być może ktoś napisze usługę zastępczą z lepszym zestawem funkcji bliżej Q.

+0

Dzięki, ale są lepsze opcje niż przy użyciu "prywatnych" członków. – Jackson

45

Chyba ten został dodany w ostatniej wersji kątowej, ale nie wydaje się być obecnie $$ obiekt stanu na obietnicy:

var deferred = $q.defer(); 
console.log(deferred.promise.$$state.status); // 0 
deferred.resolve(); 
console.log(deferred.promise.$$state.status); //1 

Jak zauważył w komentarzach nie jest to zalecane, ponieważ może to złamać podczas uaktualniania wersji Angular.

+23

Angularne dokumenty mówią, że nie należy używać właściwości '$$ ... '. Może być ryzykowne, gdy uaktualniamy do nowszych wersji Angular ... – hgoebl

+7

Zbyt zły Angular dostarcza swoje prywatne zmienne na srebrnym talerzu. :( – Jackson

+2

zobacz także: http://stackoverflow.com/questions/27039771/q-js-jest-przystąpi--przypomnieć-przypomina-jest-oddzielonym-nie--nie-nie-nieprzez – mvermand

Powiązane problemy