2015-02-11 2 views
10

Ich habe die folgende Geige: http://jsfiddle.net/thelgevold/3uv9nnjm/6/Ausführen dann nach Fang

angular.module('hello',[]).controller('helloController',function($q){ 

    console.clear(); 
    function someService(){ 
     var deferred = $q.defer(); 
     deferred.reject({e:'error'}); 
     return deferred.promise; 
    } 

    function callService(){ 
     return someService().then(function(obj){ 
      console.log('first then'); 
     }). 
     catch(function(e){ 
      console.log('error1'); 
      var deferred = $q.defer(); 
      deferred.reject({e:'error'}); 
      return deferred.promise; 
     }); 
    } 

    callService().catch(function(e){ 
     console.log('error2'); 
    }).then(function(e){ 
     console.log('second then'); 
    }); 

}); 

Es ist im Wesentlichen nur ein schnellen $ q Versprechen POC. Meine Frage ist: Warum wird die letzte then-Klausel aufgerufen, wenn das Versprechen abgelehnt wird? Die Ausgabe wird wie folgt dar:

error1

error2

Sekunden dann

Ich verstehe, warum error1/error2 gedruckt werden, aber ich dachte, die zweite Zeichenfolge sollte dann nicht gedruckt werden, da die Verheißung abgelehnt. Ich dachte, es würde "second then" aus dem gleichen Grund auslassen, aus dem das "first then" weggelassen wird. Irgendwelche Gedanken?

Antwort

13

Bevor ich beginnen, tun dies nicht:

var deferred = $q.defer(); 
deferred.reject({e:'error'}); 
return deferred.promise; 

Tun Sie dies:

return $q.reject({e:'error'}); 

oder vorzugsweise diese:

return $q.reject(new Error('error')); 

Beware the deferred antipattern.

Jetzt , für die Antwort auf yo Deine Frage.


Die .catch() nach Ihrem Anruf an callService() fängt den Fehler und produziert keinen neuen Fehler. Es hat den Fehler im Wesentlichen "behandelt", und der folgende -Handler kann frei aufgerufen werden.

Der synchrone Code-Äquivalent von Ihrem Beispiel wäre:

function someService() { 
 
    throw { e: 'error' }; 
 
} 
 

 
function callService() { 
 
    try { 
 
    var obj = someService(); 
 
    console.log('first then'); 
 
    } catch (e) { 
 
    console.log('error1'); 
 
    throw { e: 'error' }; 
 
    } 
 
} 
 

 
var e; 
 
try { 
 
    e = callService(); 
 
} catch (e) { 
 
    console.log('error2'); 
 
} 
 

 
console.log('second then');

Ich glaube, wenn man es so aussehen, ist es durchaus Sinn macht.

Der relevante Text in der Spezifikation Promises/A + ist here. Für alle Absichten und Zwecke, können Sie die catch Handler als die gleiche Sache als onRejected Handler anzuzeigen:

2.2.7. muss dann ein Versprechen abgeben [3.3].

promise2 = promise1.then(onFulfilled, onRejected);

2.2.7.1. Wenn onFulfilled oder onRejected einen Wert x zurückgibt, führen Sie die Promise Resolution Procedure [[Resolve]] (provide2, x) aus.

Grundsätzlich Ihre onRejected Handler wird "Rückkehr" der Wert undefined, so dass die von catch() erzeugte Versprechen löst mit dem Wert undefined.

+0

Danke! Das macht Sinn – TGH