2016-04-19 4 views
1

Ich habe einen Service, der Berichte erhält:

ReportsResource.getActiveUsers(). Dies verwendet $http und gibt dann ein Versprechen zurück.

ich es dann wie folgt verwenden:

var request = ReportsResource.getActiveUsers(); 

request.then(populateActiveUsersTable, handleError); 

Aber ist der Haken, dass der Antrag die aktiven Benutzer auf dem Back-End-Bericht zu bekommen kann überall von ein paar Sekunden, bis mehr als 30 Minuten dauern.

  • Wenn Sie eine Anfrage und kein zwischengespeichert Bericht zur Verfügung zu stellen, erzeugt er den Bericht, und dann wartet die Anforderung von Daten (wieder 2 Sekunden oder 30 Minuten sein könnte) für diese Anforderung.

  • Wenn Sie eine Anfrage stellen und der Bericht gerade erstellt wird, wird eine Antwort zurückgegeben, die Ihnen sofort mitteilt, dass der Bericht noch nicht fertig ist. An diesem Punkt können Sie die Abfrage fortsetzen, um zu sehen, ob der Bericht fertig ist.

  • Wenn der Bericht fertig (zwischengespeichert) ist, wird die Antwort sofort mit den Berichtsdaten zurückgegeben.

Was ich brauche, ist die Anforderung in einem Timeout wickeln, die auf 10 Sekunden warten auf und brechen dann, wenn die Antwort länger dauert als 10 Sekunden abgeschlossen und beginnt Polling den Server zu fragen, ob der Bericht fertig ist noch. Wenn die Anforderung jedoch unter 10 Sekunden aufgelöst wird, sollte das Zeitlimit aufgehoben und die Versprechungskette wie normal ausgeführt werden.

Nicht wirklich sicher, wie man damit umgeht.

Antwort

0

Unter der gegebenen Situation denke ich, es ist besser, WebSocket anstatt timeout Funktion zu verwenden. Mit WebSocket müssen Sie nur die Funktion registrieren, die Sie jedes Mal ausführen müssen, wenn ein Update/eine Änderung vom Server gesendet wird. Anstatt die Abstimmung zu halten, benötigen Websocket weniger Ressourcen und mehr Effizienz. Aber es braucht ein bisschen Arbeit am Backend.

Die Implementierung wird für unterschiedliche Back-End-Sprachen festgelegt. Sie müssen wahrscheinlich mit den Back-End-Leuten (oder sich selbst) reden. Hoffe, das kann dir eine Idee geben.

=== bearbeiten ===

Wenn Sie Service wie timeout oder interval verwenden möchten, sollten Sie den Code unten helfen:

//inside your controller 
var pollingPromise = $q.defer(); //used to controll the fired $http request 

var pollingActiveUsers = function() { 

    ReportsResource.getActiveUsers(pollingPromise).then(function(data){ 
     //stop polling 
     $interval.cancel(pollingProcess); 
     //set to the controller's scope 
     $scope.activeUsers = data; 
     //populate the activeUsersTable 
     populateActiveUsersTable(); 
    }); 
}; 

//init the first request 
pollingActiveUsers(); 

//polling for every 10secs 
var pollingProcess = $interval(function() { 
    //resolve the previous polling request which mean cancel the previous $http request if it waits longer than 10 secs 
    pollingPromise.resolve(); 

    //start another polling, a new pollingPromise is required 
    pollingPromise = $q.defer(); 

    pollingActiveUsers(); 
}, 10000); 

//In your service ReportsResource 
//you have to make another change function getActiveUsers() to make this work, you have to pass the pollingPromise to the $http method, so you can cancel the $http request: 
var function getActiveUsers = function(promiseObj) { 
    return $http.get('someUrl', { timeout: promiseObj }); 
}; 

Nur wenige Bedenken genommen werden:

  1. Bereits gefeuerte $ http-Anfrage sollte abgebrochen/gelöst werden, wenn es länger als 10 Sekunden dauert. also ist die pollingPromise die, die wir brauchen. Weitere Informationen hier: cancel unresolved promise
  2. eine neue $ http Anfrage sollte alle 10 Sekunden ausgelöst werden, $interval dieses Problem lösen und $interval.cancel() Funktion wird dieses Intervall zu stoppen.
  3. Polling sollte sofort anhalten, wenn die gewünschten Daten erhalten

Der Code geändert werden müssen möglicherweise, wenn Sie in Ihrer Anwendung gelten.

+0

Ja, das wäre ideal, leider ist das eine architektonische Umsetzung, die im Rahmen dieser speziellen Arbeit nicht möglich ist. Wir haben eine Roadmap, um dorthin zu gelangen, aber es erfordert einige asynchrone Verarbeitungsänderungen am BE, was einige Auswirkungen hat usw. – AgmLauncher

0

Verwenden Sie Winkel $q zusammen mit $timeout. Erstellen Sie einen Deferred mit $q.defer(), erstellen Sie die Anfrage mit einem Timeout und leiten Sie das Ergebnis im then-Handler weiter, um Ihre Deferred zu beheben. Wenn die Anforderungen Timeouts sind, starten Sie die Abfrage. Gib das Versprechen der Zurückgestellten sofort zurück.

var d = $q.defer() // defered for the final result 

function poll() { 
    $http({...}).then(//poll request 
     function(res) { 
      if (ready(res)) 
       d.resolve(res) 
      else { 
       $timeout(poll, 10000) 
      } 
     }, 
     function(err) { 
      d.reject(err) 
     }) 
} 

$http({ timeout: 10000, ... }).then(
    function(res) { 
     d.resolve(res) 
    }, // return result directly 
    function(err) { // error or timeout 
     if (realError(err)) // check if real error 
      d.reject(err) 
     else { //timeout 
      $timeout(poll, 10000) 
     } 
    }) 
return d.promise 

können Sie das zurückgegebene Versprechen Wiederverwendung then Aufruf beliebig oft zu warten oder das zwischengespeicherte Ergebnis zu erhalten.

Verwandte Themen