2013-05-31 11 views
33

Sto utilizzando il modulo express per creare un'API Restful all'interno di Node.JS. Nel mio servizio sto facendo richieste HTTP aggiuntive a Endpoint esterni (lato server) e ho bisogno di restituire i dati da tali richieste http al mio corpo di richiesta del servizio web.Node.JS Attendi la richiamata del servizio REST che effettua la richiesta HTTP

Ho confermato che se uso console.log su tutte le azioni che il servizio Web sta conducendo, sto ricevendo i dati di cui ho bisogno. Tuttavia, quando provo a restituire quei valori al servizio, ritornano Null. So che questo è a causa di asincrono e il callback non aspetta la fine della richiesta HTTP.

C'è un modo per farlo funzionare?

+0

È necessario accettare una richiamata. – SLaks

risposta

41

Una pratica comune è utilizzare il modulo async.

npm install async 

Il modulo async ha primitive per gestire le varie forme di eventi asincroni.

Nel tuo caso, la chiamata async#parallel ti consentirà di effettuare richieste a tutte le API esterne contemporaneamente e combinare i risultati per la restituzione al richiedente.

Poiché si stanno facendo richieste http esterne, probabilmente si troverà utile anche il modulo request.

npm install request 

Utilizzando request e async#parallel vostro gestore di percorso sarebbe simile a questa ...

var request = require('request'); 
var async = require('async'); 

exports.handler = function(req, res) { 
    async.parallel([ 
    /* 
    * First external endpoint 
    */ 
    function(callback) { 
     var url = "http://external1.com/api/some_endpoint"; 
     request(url, function(err, response, body) { 
     // JSON body 
     if(err) { console.log(err); callback(true); return; } 
     obj = JSON.parse(body); 
     callback(false, obj); 
     }); 
    }, 
    /* 
    * Second external endpoint 
    */ 
    function(callback) { 
     var url = "http://external2.com/api/some_endpoint"; 
     request(url, function(err, response, body) { 
     // JSON body 
     if(err) { console.log(err); callback(true); return; } 
     obj = JSON.parse(body); 
     callback(false, obj); 
     }); 
    }, 
    ], 
    /* 
    * Collate results 
    */ 
    function(err, results) { 
    if(err) { console.log(err); res.send(500,"Server Error"); return; } 
    res.send({api1:results[0], api2:results[1]}); 
    } 
); 
}; 

Si può anche leggere su altri metodi di callback sequenziamento here.

+0

Questo sembra promettente. Come potrei invocare questo? – Rob

+0

capito. Grazie! – Rob

+0

Wow. Mi hai appena risparmiato ore di ricerca –

17

Node.js è tutto sui callback. A meno che la chiamata API sia sincrona (rara e non dovrebbe essere eseguita) non si restituiscono mai i valori da tali chiamate, ma si richiama il risultato dal metodo callback o si richiama il metodo express res.send

Una grande libreria per invocando richieste web è request.js

Facciamo l'esempio molto semplice di chiamare google. Utilizzando res.send, il codice express.js potrebbe assomigliare:

var request = require('request'); 
app.get('/callGoogle', function(req, res){ 
    request('http://www.google.com', function (error, response, body) { 
    if (!error && response.statusCode == 200) { 
     // from within the callback, write data to response, essentially returning it. 
     res.send(body); 
    } 
    }) 
}); 

In alternativa, è possibile passare un callback per il metodo che richiama la richiesta web, e invocare che richiamata dall'interno di quel metodo:

app.get('/callGoogle', function(req, res){ 
    invokeAndProcessGoogleResponse(function(err, result){ 
    if(err){ 
     res.send(500, { error: 'something blew up' }); 
    } else { 
     res.send(result); 
    } 
    }); 
}); 

var invokeAndProcessGoogleResponse = function(callback){ 
    request('http://www.google.com', function (error, response, body) { 

    if (!error && response.statusCode == 200) { 
     status = "succeeded"; 
     callback(null, {status : status}); 
    } else { 
     callback(error); 
    } 
    }) 
} 
3

wait.for https://github.com/luciotato/waitfor

Altri esempi di risposta utilizzando wait.for:

Esempio da da risposta di Daniel (async), ma utilizzando Wait.for

var request = require('request'); 
var wait = require('wait.for'); 

exports.handler = function(req, res) { 
try { 
    //execute parallel, 2 endpoints, wait for results 
    var result = wait.parallel.map(["http://external1.com/api/some_endpoint" 
       ,"http://external2.com/api/some_endpoint"] 
       , request.standardGetJSON); 
    //return result 
    res.send(result); 
} 
catch(err){ 
    console.log(err); 
    res.end(500,"Server Error") 
} 
}; 

//wait.for requires standard callbacks(err,data) 
//standardized request.get: 
request.standardGetJSON = function (options, callback) { 
    request.get(options, 
      function (error, response, body) { 
       //standardized callback 
       var data; 
       if (!error) data={ response: response, obj:JSON.parse(body)}; 
       callback(error,data); 
      }); 
} 
Problemi correlati