2013-05-30 15 views
8

Próbuję wymyślić dobry sposób, aby powiedzieć: „Czy wszystkie te rzeczy, ale za kaucją w przypadku, gdy któryś z nich zawodzi”Zatrzymywanie angularjs łańcuch obietnica

Co mam teraz:

var defer = $q.defer(); 

this 
    .load(thingy) // returns a promise 

    .then(this.doSomethingA.bind(this)) 
    .then(this.doSomethingB.bind(this)) 
    .then(this.doSomethingC.bind(this)) 
    .then(this.doSomethingD.bind(this)) 

    .then(function(){ 
     defer.resolve(this); 
    }); 
    ; 

return defer.promise; 

Ostatecznie chcę jakoś złapać jakikolwiek błąd w tym łańcuchu, więc mogę go przekazać na powyższą obietnicę defer. Nie obchodzi mnie szczególnie, czy składnia jest podobna do tego, co mam powyżej.

Nawet jeśli ktoś może mi powiedzieć, jak zatrzymać powyższy łańcuch.

+1

@ user2246674 - odrzucając to nie wydaje się zatrzymywać łańcucha, następny kontynuuje –

+1

Nie wiem o czym myślałem .. – user2246674

+2

To jest przerażający przykład [odroczonego antipattern] (http: //stackoverflow.com/q/23803743/1048572)! Przykręć 'odroczenie', po prostu' zwróć '' this.load (...) .then (A) .then (B) .then (C) .then (D); 'chain! – Bergi

Odpowiedz

2

Powinieneś być w stanie zrobić to samo przez:

var defer = $q.defer(); 

this 
    .load(thingy) // returns a promise 

    .then(this.doSomethingA.bind(this), $q.reject) 
    .then(this.doSomethingB.bind(this), $q.reject) 
    .then(this.doSomethingC.bind(this), $q.reject) 
    .then(this.doSomethingD.bind(this), $q.reject) 

    .then(defer.resolve.bind(defer, this), defer.reject.bind(defer)); 
    ; 

return defer.promise; 
+3

Ta odpowiedź używa wzorca zapobiegawczego i powoduje, że użytkownik powtarza obsługę błędów. –

0

Dobra, to działa, ale nie podoba mi się to ... Czekamy na coś lepszego :)

prostu wydaje się brudna stworzyć obiecujące dla jedynego dobra natychmiast odrzucenia

myApp 
    .factory('chainReject', [ '$q', function($q){ 
     return function(err){ 
      var defer = $q.defer(); 
      defer.reject(err); 

      return defer.promise; 
     } 
    } ]); 

... 

var defer = $q.defer(); 

this 
    .load(thingy) // returns a promise 

    .then(this.doSomethingA.bind(this), chainReject) 
    .then(this.doSomethingB.bind(this), chainReject) 
    .then(this.doSomethingC.bind(this), chainReject) 
    .then(this.doSomethingD.bind(this), chainReject) 

    .then(defer.resolve.bind(defer, this), defer.reject.bind(defer)); 
    ; 

return defer.promise; 
5

Możesz zatrzymać łańcuch angularjs, zwracając odrzuconą obietnicę w ramach każdego połączenia zwrotnego.

load() 
.then(doA) 
.then(doB) 
.then(doC) 
.then(doD); 

gdzie DOA, Dob, doC, DOD może mieć logiki tak:

var doA = function() { 
    if(shouldFail) { 
     return $q.reject(); 
    } 
} 
+1

+1 Co to było dla mnie to 'return' część' return $ q.reject() '. Wiele wyszukiwań prowadziło na wiele różnych sposobów, ale w rzeczywistości zwracało $ q.reject() zamiast tylko wywoływać to, co faktycznie zabija łańcuch. Szczególnie jeśli próbujesz zrobić coś, co nie jest awarią HTTP, ale "niepowodzenie" w tym sensie, że model zwrócił z oczekiwaną negatywną odpowiedzią. – coblr

+0

Innym sposobem zatrzymania łańcucha, powiedz, że chcesz pokazać błędy, które wystąpiły podczas wykonywania łańcucha, możesz po prostu "rzucić nowy błąd"() –

+0

Odrzucenie odrzuconej obietnicy nie zatrzyma łańcucha. – user3631341

3

Właśnie natknęliśmy się na to i zrozumiał wszystkie te odpowiedzi są strasznie przestarzałe. Oto właściwa metoda rozwiązania tego problemu dla każdego, kto znajdzie ten wpis.

// Older code 
return this.load(thing) 
    .then(this.doA, $q.reject) 
    .then(this.doB, $q.reject) 
    .then(this.doC, $q.reject) 
    .then(this.doD, $q.reject) 
    .then(null, $q.reject); 


// Updated code 
// Returns the final promise with the success handlers and a unified error handler 
return this.load(thing) 
    .then(this.doA) 
    .then(this.doB) 
    .then(this.doC) 
    .then(this.doD) 
    .catch(this.handleErrors); // Alternatively, this can be left off if you just need to reject the promise since the promise is already rejected. 
    // `.catch` is an alias for `.then(null, this.handleErrors);` 
+0

'.catch' nie istniało w' $ q', gdy zadano to pytanie :) –

+0

@zyklus, masz rację, ale '.catch' jest po prostu aliasem dla' .then (null, fn) '. Które powinny być wtedy ważne. –

+0

Nie był on używany do przekazywania błędów przez, to znaczy, przechwytywałby tylko błędy z poprzedniego 'wtedy', dlatego napisałem poniżej wszystkie bzdury odrzuceń łańcucha. –

0

Najlepszym sposobem na poradzenie sobie z tym problemem jest blok .catch. Wewnątrz każdej .Następnie bloku, który chcesz zabić łańcuch obietnica tak Zastosowanie:

return $q.reject(); 

jednak przedłużyć go tak jak ...

return $q.reject(new Error('Error Message Here')); 

Teraz w metodzie połowu będzie mieć ten

.catch(function(err) { 
    console.log(err); //This will log the above 'Error Message Here' 
}); 

Teraz rzucamy i prawidłowo obsługujemy błąd obietnicy w ramach obietnicy mody, która miała zostać rozwiązana.