2013-05-31 12 views
33

Używam modułu ekspresowego do tworzenia restful API w Node.JS. W mojej usłudze wysyłam dodatkowe żądania http do zewnętrznych punktów końcowych (po stronie serwera) i potrzebuję zwrócić dane z tych żądań http do mojej treści żądania usługi internetowej.Węzeł.JS Czekaj na oddzwonienie usługi REST, która wysyła żądanie HTTP

Potwierdziłem, że jeśli użyję console.log we wszystkich działaniach, które prowadzi serwis internetowy, otrzymam potrzebne dane. Jednak gdy próbuję zwrócić te wartości do usługi, wracają one do wartości Null. Wiem, że dzieje się tak z powodu asynchronizacji, a wywołanie zwrotne nie czeka na zakończenie żądania http.

Czy istnieje sposób, aby to zadziałało?

+0

Musisz zaakceptować wywołanie zwrotne. – SLaks

Odpowiedz

41

Powszechną praktyką jest używanie modułu async.

npm install async 

Moduł async ma prymitywów obsługiwać różne formy asynchronicznych zdarzeń.

W twoim przypadku wywołanie async#parallel pozwala na wysyłanie żądań do wszystkich zewnętrznych interfejsów API w tym samym czasie, a następnie łączenie wyników dla ciebie z powrotem.

Ponieważ tworzysz zewnętrzne żądania http, prawdopodobnie będzie ci pomocny również moduł request.

npm install request 

Korzystanie request i async#parallel programu obsługi trasa będzie wyglądać następująco ...

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

Można również przeczytać o innych metod sekwencjonowania here zwrotna.

+0

To wygląda obiecująco. Jak mógłbym to przywołać? – Rob

+0

wymyśliłem to. Dzięki! – Rob

+0

Wow. Po prostu zaoszczędzisz mi godzin wyszukiwania –

17

Na Node.js chodzi o wywołania zwrotne. O ile wywołanie API nie jest synchroniczne (rzadkie i nie powinno być wykonywane), nigdy nie zwracaj wartości z tych wywołań, ale wywołaj zwrotnie z wynikiem z metody wywołania zwrotnego lub wywołaj metodę ekspresową res.send

Świetna biblioteka dla wywoływanie żądań internetowych to request.js

Weźmy naprawdę prosty przykład wywoływania google. Korzystanie res.send, kod express.js mógłby wyglądać następująco:

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

Alternatywnie, można przekazać wywołania zwrotnego do metody, która powołuje się na wniosek stron internetowych, i powołać się na tę zwrotnego od wewnątrz tej metody:

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

Inne przykłady wykorzystujące wait.for odpowiedź brzmi:

przykład od od Daniela Odpowiedź (asynchronicznie), ale przy użyciu 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); 
      }); 
} 
Powiązane problemy