Expressモジュールを使用して、Node.JS内でRestful APIを作成しています。私のサービスでは、外部のエンドポイント(サーバー側)に追加のHTTPリクエストを作成しています。これらのHTTPリクエストからのデータをWebサービスリクエスト本文に返す必要があります。
Webサービスが実行しているすべてのアクションでconsole.log
を使用すると、必要なデータを取得できることを確認しました。ただし、これらの値をサービスに返そうとすると、Nullが返されます。これは非同期が原因であり、コールバックがhttp要求の終了を待機していないことがわかっています。
この作品を作る方法はありますか?
一般的な方法は、 async モジュールを使用することです。
npm install async
async
モジュールには、さまざまな形式の非同期イベントを処理するプリミティブがあります。
あなたの場合、async#parallel
呼び出しにより、すべての外部APIに同時に要求を行い、結果を結合して要求者に返すことができます。
外部のHTTPリクエストを作成しているので、おそらく request モジュールも役立つでしょう。
npm install request
request
とasync#parallel
を使用すると、ルートハンドラは次のようになります。
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]});
}
);
};
他のコールバックシーケンスメソッドについても読むことができます here 。
Node.jsはコールバックに関するものです。 API呼び出しが同期的でない場合(まれに実行されるべきではありません)、それらの呼び出しから値を返すことはありませんが、コールバックメソッド内からの結果でコールバックするか、expressメソッドres.sendを呼び出します
Webリクエストを呼び出すための優れたライブラリはrequest.jsです
Googleを呼び出す実際の簡単な例を見てみましょう。 res.sendを使用すると、express.jsコードは次のようになります。
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);
}
})
});
または、Web要求を呼び出すメソッドにコールバックを渡し、そのメソッド内からそのコールバックを呼び出すことができます。
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);
}
})
}
Wait.for https://github.com/luciotato/waitfor
Wait.forを使用した他の回答の例:
Daniel's Answer(async)の例ですが、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);
});
}