2013-12-13 12 views
16

Ich versuche, einige lokale Daten zu füllen, die eine Reihe von Remoteaufrufen lösen.
Wenn jedes Versprechen gelöst ist, lade ich die Daten und fahre fort.

Die Methode $q.all([]) tut genau dies:

 $q.all([ 
      this.getUserInfo(11) 
       .then(function (r) { 
        results.push(r) 
       }), 

      this.getUserConns() 
       .then(function (r) { 
        results.push(r) 
       }), 

      this.getUserCtxs() 
       .then(function (r) { 
        results.push(r) 
       }) 
     ]) 
     .then(function() { 
      console.log(results) 
     }) 


Problem ist, ist dieser Code nicht elastisch.
Wenn einer dieser Anrufe fehlschlägt, bekommt niemand den Fisch!

Umwickeln die Anrufe in einer try/catch-Anweisung verursacht einfach $q.all() zu ganz den Eintrag zu ignorieren, auch wenn sie nicht (man beachte die console.log in der func) versagt ...

 $q.all([ 
      this.getUserInfo2(11) 
       .then(function (r) { 
        results.push(r) 
       }), 

      function() { 
       try { 
        this.getUserGroups() 
         .then(function (r) { 
          console.log(r) 
          results.push(r) 
         }) 
       } 
       catch (err) { 
        console.log(err) 
       } 
      }, 
     ]) 
     .then(function() { 
      console.log(results) 
     }) 

Ausgang:

[Objekt]


Irgendein Hinweis darauf, wie ich dies umwickeln könnte, um belastbar zu sein?


Dank @dtabuenc bin ich noch einen Schritt weiter gegangen. Durch die Implementierung des Fehlerrückrufs kann ich das Brechen der Kette vermeiden und die Werte der aufgelösten Versprechen verschieben.

Allerdings wird immer noch eine unangenehme Ausnahme auf der Konsole angezeigt ... Wie kann ich das loswerden, wenn ich Async-Anfragen nicht versuchen/fangen kann?

Anrufercode

return $q.all([ 

      this.getUserInfo(user_id) 
       .then(function (r) { 
        results['personal_details'] = r 
       }), 

      this.getUserConns() 
       .then(
        function (r) { 
        results['connections'] = r 
        }, 
        function(err) { 
         console.log(err) 
        }) 

     ]) 
     .then(function() { 
      return (results) 
     }) 

Callee Code (injizieren mit einer Ausnahme)

getUserConns: function() { 

     return __doCall(ws.getUserConnections, {}) 
      .then(function(r) { 

       // very generic exception injected 
       throw new Error 

       if (r && r.data['return_code'] === 0) { 
        return r.data['entries'] 
       } 
       else { 
        console.log('unable to retrieve the activity - err: '+r.data['return_code']) 
        return null 
       } 
      }) 
    }, 

Antwort

23

Dies wird funktionieren, aber auch die Fehler auf das Array schieben.

function push(r) { 
    results.push(r); 
} 

$q.all([ 
    this.getUserInfo(11).then(push).catch(push), 
    this.getUserConns().then(push).catch(push), 
    this.getUserCtxs().then(push).catch(push) 
]) 
.then(function() { 
    console.log(results); 
}) 

Sie sollten auch Ihr Verständnis von Versprechen verbessern, Sie nietry-catch mit dem Versprechen verwenden sollten - wenn Versprechen verwenden, verwenden Sie die .catch() Methode (mit allem anderen implizit eine try ist). Dies funktioniert sowohl bei normalen Fehlern als auch bei asynchronen Fehlern.


Wenn Sie möchten, um die Fehler zu völlig ignorieren:

function push(r) { 
    results.push(r); 
} 

function noop() {} 

$q.all([ 
    this.getUserInfo(11).then(push).catch(noop), 
    this.getUserConns().then(push).catch(noop), 
    this.getUserCtxs().then(push).catch(noop) 
]) 
.then(function() { 
    console.log(results); 
}) 
+0

Eigentlich bin ich noch ein Newbie auf Angular, verspricht und sogar JS, und ich bin mehr als glücklich, jeden Tag neue Dinge zu lernen! Die .catch() -Methode "blockiert" die Ausnahme nicht, die ich bei meinem letzten Beispiel spawne, aber ich denke, es ist am nächsten zu meinem idealen Ergebnis. Danke! – domokun

+1

@ Domokun Winkel verspricht fälschlicherweise berichten sogar gefangen Ausnahmen, verletzen den Geist der Versprechen/A + wenn nicht gegen die Spezifikation – Esailija

+0

Gut zu wissen ... Ich denke ... Thx wieder! – domokun

0

Ich bin nicht sicher, was Sie durch elastische bedeuten. Was willst du tun, wenn eines der Versprechen fehlschlägt?

Ihr try-catch funktioniert nicht, weil das Versprechen asynchron fehlschlägt.

Sie können jedoch einen Fehlerhandler als zweiten Parameter an den then() Aufruf übergeben und tun, was Sie dort wünschen.

+0

Ok gut, ich habe den Fehler Rückruf vergessen. Es ist elastisch in dem Sinne, dass die Kette nicht unterbrochen wird, und das ist, was ich wollte. Allerdings kann ich die Ausnahme nicht verstecken, wenn ich es nicht fangen ... Ich werde meine Frage zu erklären, – domokun

+0

Ich glaube nicht, dass Sie HTTP-Fehler abfangen können. Sie werden immer auf der Konsole angezeigt. Dies ist unabhängig davon, ob Sie eckig oder nicht verwenden. – dtabuenc

+0

Das stimmt, und stört mich nicht. Was mich wirklich stört, ist eine Ausnahme auf der Konsole. Bitte werfen Sie einen Blick auf meine aktualisierte Frage – domokun

0

gleiche Problem hier. Für diejenigen von Ihnen mit for-Schleifen: in einer Antwort dann:

var tracks = []; 
var trackDfds = []; 
for(var i = 0; i < res.items.length; i++){ 
    var fn = function() { 
     var promise = API.tracks(userId, res.items[i].id); 
     return promise.then(function (res) { 
      if (res.items.length) { 
       tracks.push(res.items); 
      } 
     }).catch(angular.noop); 
    }; 
    trackDfds.push(fn()); 
} 
$q.all(trackDfds) 
    .then(function (res) { 
     console.log(tracks); 
    }); 
1

ich denke, es ist einfacher zu tun:

$q.all([ 
mypromise1.$promise.catch(angular.noop), 
mypromise2.$promise.catch(angular.noop), 
mypromise1.$promise.catch(angular.noop) 
]) 
.then(function success(data) { 
//..... 
}); 
0

@ Esailija Antwort wie eine Abhilfe für ein Problem zu sein scheint. Sie können das Problem außerhalb des Hauptbeitrags zu dem Problem nicht lösen: $q.

Es scheint ein wenig weiser zu haben, Rückrufe für jede then (2. Argument) abzulehnen und darin $q.reject(...) einzufügen.

Beispiel:

$q.all([ 
    this.getUserInfo(11).then(
     function (response) { // UI data preparation for this part of the screen }, 
     function (response) { 
      $q.reject(response); 
     } 
    ), 
    // ... 
]) 
.then(
    function() { 
     // all good 
    }, 
    function() { 
     // at least one failed 
    } 
) 

Dies ist besonders angezeigt, wenn das UI-Modell auf alle Ajax-Aufrufe abhängig ist.

Persönlich denke ich, das ist der sichere Weg, trotzdem zu gehen, weil die meisten Zeiten Sie möchten einige Server Nachrichten an einige Toast-Komponente auf die Ablehnen Rückrufe schieben oder den Benutzer in irgendeiner Weise warnen (Warteschlange 7 Ajax Anrufe Das bedeutet nicht, dass Sie nichts zeigen können, weil 1 fehlgeschlagen ist - es bedeutet, dass Sie einige Bereiche des Bildschirms nicht anzeigen können - die eine spezielle Rückmeldung an den Benutzer benötigen.