2014-06-27 7 views
59

Próbuję uzyskać uchwyt usługi Angular $q i powiązanych obiektów i interfejsów API. Kiedy patrzę na obiektach w mojej konsoli widzę:

var deferred = $q.defer() 

...(and then from console inspection)... 

$q: Object {defer: function, reject: function, when: function, all: function} 

deferred: Object {resolve: function, reject: function, notify: function, promise: Object} 

deferred.promise: Object {then: function, catch: function, finally: function} 

To rodzi kilka pytań:

  1. Jaka jest różnica między $q.reject() i deferred.reject()? Kiedy używać każdego?
  2. Jaki jest związek między errorFn w deferred.promise.then(successFn, errorFn) i catchFn w deferred.promise.catch(catchFn)?
  3. Jeśli mam garść zagnieżdżonych obietnic i wystąpi błąd, czy zawsze będzie wywoływana zewnętrzna funkcja catch()? Co się stanie, jeśli jedna z zagnieżdżonych obietnic ma również zdefiniowaną funkcję catch? Czy to złapanie uniemożliwi wykonanie najbardziej oddalonego połowu?

Dzięki.

Odpowiedz

86

1) $q.reject() to skrót do tworzenia odroczonego, a następnie natychmiast go odrzucić; Często używam tego w errorFn, jeśli nie mogę obsłużyć błędu.

2) Nic promise.catch(errorFn) jest po prostu cukier syntaktyczny dla promise.then(null, errorFn), podobnie jak sukces i błędów metod służby $http, więc można napisać kod jak poniżej:

promise. 
    then(function(result){ 
     // handle success 
     return result; 
    }, function errorHandler1(error){ 
     // handle error, exactly as if this was a separate catch in the chain. 

    }).catch(function errorHandler2(error){ 
     // handle errors from errorHandler1 
    }); 

3) To jest dokładnie tam, gdzie $ q.reject może się przydać:

promise. 
    catch(function(error){ 
     //Decide you can't handle the error 
     return $q.reject(error); //This forwards the error to the next error handler; 
    }).catch(function(error){ 
     // Here you may handle the error or reject it again. 
     return 'An error occurred'; 
     //Now other errorFn in the promise chain won't be called, 
     // but the successFn calls will. 
    }).catch(function(error){ 
     // This will never be called because the previous catch handles all errors. 
    }).then(function(result){ 
     //This will always be called with either the result of promise if it was successful, or 
     //'An error occured' if it wasn't 
    }); 
+0

Dzięki za zwięzłe odpowiedzi. Są bardzo jasne.Nadal utknąłem na numerze # 2. Załóżmy, że Twój przykładowy kod zawiera zarówno successFn, ​​jak i errorFn w twoim wywołaniu do then(). Teraz w jakich okolicznościach uruchomi się catchFn? – lostdorje

+0

Zaktualizowałem moją odpowiedź na 2). Metoda catch jest dokładnie taka sama, jak drugi argument funkcji then. promise.catch (errorFn) jest identyczny z promise.then (null, errorFn). – dustyrockpyle

+1

Jeśli ktoś chce przeczytać dalej, kiedy użyć '$ q', uznałem, że ten artykuł jest bardzo pomocny http://www.codelord.net/2015/09/24/$q-dot-defer-youre-doing-it-wrong / – Chris

4

OK, to jest moje ujęcie obietnic.

  1. $q.reject(reason) zwraca odrzuconą obietnicę z przyczyną przekazaną jako argument i odroczoną. Odrzuć odrzuca istniejącą zależność, czy proces się zakończył, czy nie.

  2. errorFn zostaje uruchomiona, gdy obietnica zostaje odrzucona, a jej argument jest przyczyną odrzucenia. Złapanie jest wywoływane, gdy błąd w procesie obietnicy nie był właściwie obsługiwany, powodując obietnicę podniesienia i wyjątku i nie został odrzucony ani spełniony.

  3. Nie należy zawierać zagnieżdżonych obietnic, powinieneś mieć przykuty obietnice, w którym to przypadku najnowszy blok catch powinien wychwycić wszystko przed nim, jeśli żaden inny blok nie został określony, aby go obsłużyć.

+0

Dla # 2 widzisz, jeśli jestem w moim successFn lub errorFn i zrobić rzut nowy błąd (...) wtedy catchFn będzie działać? Rozumiem, że tak nie jest. – lostdorje

+0

może znajdować się w modułach obsługi lub w procesie. w procesie na pewno będzie to złapać, ale myślę, że hanlder zbyt –

+0

chodzi o to, że w procesie mogą wystąpić błędy, które mogłyby uniemożliwić przejście z obietnicy do dowolnego stanu, więc blok catch jest używany do wykrywania tych błędów, na przykład, jeśli twój porcess wykona podział, a spróbujesz podzielić przez 0, podniossz wyjątek, który automatycznie zakończy proces, jeśli nie jest buforowany i obsługiwany. blok catch to dostanie i będzie działał zgodnie z przepisami. może uda mi się udate moje pytanie, ponieważ napadam to jest właściwe zachowanie –