2014-09-19 14 views
9

Quindi ho un metodo Meteor che dovrebbe dire al server di inviare più richieste API a API di terze parti e quindi combinare i risultati di queste query in un array, che viene restituito al client.meteora - Sincronizzare più query asincrone prima di tornare?

Tuttavia, non riesco a trovare un modo per il server di attendere il completamento di tutte le query dell'API prima di restituire il risultato.

La versione sincrona del codice, che ha appena recupera la chiamata dati API dopo l'altro, va così:

Meteor.methods({ 
    fetchData: function(APILinks) { 
     var data = []; 
     APILinks.forEach(function(APILink) { 
      var items = HTTP.get(APILink).content.items; 
      items.forEach(function (item) { 
       data.push(item); 
      }); 
     }); 
     return items; 
    } 
}); 

Questo codice sincrono funziona. Tuttavia, non sono stato in grado di trovare un buon modo per rendere le richieste API asincrone. Il più vicino possibile a una soluzione era ridefinire il metodo per restituire il risultato di una sola richiesta API e quindi fare in modo che il client effettuasse il ciclo attraverso ciascun link dell'API e chiamasse il metodo per ognuno di essi. Tuttavia, c'è un modo per racchiudere tutte queste richieste in un unico metodo che restituisce solo quando tutte le richieste API sono complete?

risposta

12

È necessario utilizzare la versione asincrona di HTTP.get e raccogliere i risultati utilizzando Future s.

Ho creato un semplice esempio utilizzando setTimeout s per simulare le richieste HTTP in modo che tu capisca il principio, ti consiglio di iniziare da questo codice e sostituire il manichino setTimeout con la richiesta di ottenere HTTP.

L'esempio è un metodo server test che accetta un numero di attività (n) come parametro, quindi avvia n attività che calcolano ciascuna il quadrato del proprio indice in secondi dell'indice.

// we use fibers which is a dependency of Meteor anyway 
var Future = Npm.require("fibers/future"); 

Meteor.methods({ 
    test: function(n) { 
     // build a range of tasks from 0 to n-1 
     var range = _.range(n); 
     // iterate sequentially over the range to launch tasks 
     var futures = _.map(range, function(index) { 
      var future = new Future(); 
      console.log("launching task", index); 
      // simulate an asynchronous HTTP request using a setTimeout 
      Meteor.setTimeout(function() { 
       // sometime in the future, return the square of the task index 
       future.return(index * index); 
      }, index * 1000); 
      // accumulate asynchronously parallel tasks 
      return future; 
     }); 
     // iterate sequentially over the tasks to resolve them 
     var results = _.map(futures, function(future, index) { 
      // waiting until the future has return 
      var result = future.wait(); 
      console.log("result from task", index, "is", result); 
      // accumulate results 
      return result; 
     }); 
     // 
     console.log(results); 
     return results; 
    } 
}); 

Digitare > Meteor.call("test",3,function(error,result){console.log(result);}); nella console del browser. Questo produrrà [0,1,4] dopo 3 secondi.

Nella console del server, questa uscita volontà:

// immediately : 
launching task 0 
launching task 1 
launching task 2 
// after 1 second : 
result from task 0 is 0 
// after 2 seconds : 
result from task 1 is 1 
// after 3 seconds : 
result from task 2 is 4 
[ 0, 1, 4 ] 

La versione asincrona HTTP.get è dettagliato nei documenti Meteor:

http://docs.meteor.com/#http_call

Se si vuole capire meglio l'intero Future concetto, fare riferimento alle fibre doc:

https://github.com/laverdet/node-fibers

+0

Meteor ha una fresca astrazione dei futures: Meteor._wrapAsync, evviva per evitare Lo standard –

+4

'Meteor.wrapAsync' è utile quando si desidera trasformare task asincroni in chiamate sincrone procedurali successive, ma non sarà di aiuto qui perché ciò che vogliamo ottenere è l'avvio simultaneo di più task asincroni che vogliamo eseguire in parallelo. Inoltre, non sarebbe inutile utilizzare 'Meteor.wrapAsync' per racchiudere' HTTP.get' perché sta già esponendo una versione sincrona disponibile quando non si inoltra alcun callback come argomento. – saimeunt

Problemi correlati