Node.JS Attendez le rappel de REST Service qui fait une demande HTTP

J'utilise le module express pour créer une API reposante dans Node.JS. Dans mon service, je fais des requêtes HTTP supplémentaires vers des points d'extrémité externes (côté serveur) et je dois renvoyer les données de ces requêtes http à mon corps de demande de service Web.

J'ai confirmé que si j'utilise console.log sur toutes les actions que le service Web effectue, je reçois les données dont j'ai besoin. Cependant, lorsque j'essaie de renvoyer ces valeurs au service, elles reviennent null. Je sais que cela est dû à l'asynchrone et le rappel n'est pas en attente de la demande http pour terminer.

Existe-t-il un moyen de faire fonctionner cela?

Une pratique courante est d'utiliser le module asynchrone .

 npm install async 

Le module async comporte des primitives pour gérer diverses formes d'événements asynchrones.

Dans votre cas, l'appel async#parallel vous permettra de faire des requêtes à toutes les API externes en même temps et ensuite combiner les résultats pour retourner à votre demandeur.

Puisque vous faites des requêtes HTTP externes, vous trouverez également le module de demande également utile.

 npm install request 

En utilisant request and async#parallel votre gestionnaire d'itinéraire ressemblerait à ceci …

 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]}); } ); }; 

Vous pouvez également lire ici les autres méthodes de séquençage de rappel.

Node.js concerne tous les rappels. Sauf si l'appel de l'API est synchrone (rare et ne doit pas être fait), vous ne renvoyez jamais les valeurs de ces appels, mais le rappel avec le résultat à partir de la méthode de rappel ou appelez la méthode express res.send

Une excellente bibliothèque pour invoquer les requêtes Web est request.js

Prenons l'exemple vraiment simple d'appeler Google. En utilisant res.send, votre code express.js pourrait ressembler à:

 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); } }) }); 

Alternativement, vous pouvez passer un rappel à la méthode qui invoque la demande Web et invoquez ce rappel à partir de cette méthode:

 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); } }) } 

Attendez. Pour https://github.com/luciotato/waitfor

Les exemples d'autres réponses utilisant wait.for:

Exemple de la réponse de Daniel (async), mais en utilisant 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); }); }