2013-02-27 23 views
14

Sto ancora avvolgendo il mio cervello intorno a Angular.JS.Angular.JS Spegnere due chiamate di servizio asincrono, quindi eseguire un'azione dopo aver completato entrambi

Ho due chiamate $ http indipendenti che recuperano i dati dai servizi Web remoti. Ho un'azione che desidero attivare dopo che entrambe le chiamate di assistenza sono state completate.

  1. La prima chiamata di servizio popola il $ scope.model
  2. La seconda chiamata di servizio, modifica i dati nel $ scope.model (aggiunge alcune proprietà di contatori sono resi nella vista)

Un altro requisito univoco è che alla fine la seconda chiamata di servizio verrà richiamata e aggiornata all'esterno del controller con $ scope.model. È una pompa per i messaggi di notifica.

Sto supponendo che userò promesse $ q e possibilmente $ servizio, ma non sono davvero sicuro da dove iniziare per qualcosa di simile seguendo alcune best practice.

So che non sembra che le chiamate asincrone siano appropriate qui, poiché il mio esempio potrebbe essere semplificato facendolo in modo sincrono. Tuttavia, la seconda chiamata di servizio è un aggiornamento della notifica, quindi verrà continuamente interrogato sul server (eventualmente verrà utilizzato un websocket).

È uno schema comune che vedrò in questa applicazione.

risposta

29

Ti consigliamo di utilizzare $ q promette In particolare $ q.all(). Tutti i metodi $ http restituiranno promesse. $q.all([promise, promise, promise]).then(doSomething) attenderà che tutte le promesse si risolvano, quindi chiama doSomething passando ad esso un array di risultati promessi.

app.service('myService', ['$http', '$q', function($http, $q) { 
    return { 
     waitForBoth: function() { 
      return $q.all([ 
      $http.get('/One/Thing'), 
      $http.get('/Other/Thing') 
      ]); 
     }; 
    } 
}]); 

Poi lo chiamano:

app.controller('MyCtrl', ['$scope', 'myService', function($scope, myService) { 
    myService.waitForBoth().then(function (returnValues){ 
     var from1 = returnValues[0].data; 
     var from2 = returnValues[1].data; 
     //do something here. 
    }); 
}]); 

Ecco una dimostrazione Plunker per voi.

+0

Inizialmente con questa versione della risposta. In futuro, potrei cambiare il mio codice per vedere la proprietà per le modifiche, poiché alla fine sarà in ascolto di un messaggio pump. E punti bonus per l'uso della sintassi della dichiarazione di servizio minifiable nel codice di esempio. – taudep

+0

Haha ... Non vedo punti bonus! : P Ho cambiato la dichiarazione del controller per avere anche la sintassi minify-friendly. Sono contento di poterti aiutare. –

+0

Grazie per aver scritto che è necessario passare una serie di valori ..... argg mi è mancato per un po '! –

2

Creare un servizio per la prima chiamata di servizio. La risposta di Pete aiuterà con che: https://stackoverflow.com/a/12513509/215945

nel controller, nel callback allora(), aggiungere un orologio $ per la proprietà $ scope.model appropriata:

app.controller('MainCtrl', function(myService, $scope) { 
    myService.async().then(function(myData) { 
    $scope.model = myData; 
    $scope.$watch('model.???', function(newVal, oldVal) { 
     if(newVal !== oldVal) { 
     // do something here, now that $scope.model.??? has changed 
     } 
    }) 
    }); 
}); 
+1

Sembra che sia l'ora del giorno in cui scambio le risposte con @MarkRajcok –

+0

Giocare con entrambe le soluzioni. Grazie! Ne segnerò uno come completo al più presto. Mi piacerebbe rendere i dati nella prima chiamata prima che la seconda chiamata sia necessariamente completata, quindi $ watch sul modello è probabilmente la chiave per me sopra l'idea waitForBoth di seguito. – taudep

Problemi correlati