APIを叩いた結果をもってさらにAPIを叩くということをnode.jsで実現するには、Promiseの仕組みを使うことが必須に思えます。
最初のAPIの結果を取得するにも、次のAPIの結果を取得するにも「待ち」が発生するため、非同期処理を施してあげないとウェブアプリ全体が止まってしまうことになります。
また、Promiseを使うことで、最初のAPIの結果を受け取り→次のAPIへの通信という順番も担保されます。
処理の流れ
最初のAPIに問い合わせることで、アクセス用トークンを受け取り、そのトークンをもって更にAPIに問い合わせます。
var express = require('express');
var rp = require('request-promise-native');
var router = express.Router();
// トークンを問い合わせ
async function renewToken() {
let username = 'user';
let passwd = 'passwd';
let authEndPoint = 'https://api.com/auth/';
let options = {
resolveWithFullResponse: true,
uri: authEndPoint,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
json: {
'username': username,
'password': passwd
}
};
try {
let result = await rp(options);
if (result['statusCode'] !== '200') {
throw 'No return token';
} else {
return result['body']['token'];
}
} catch (err) {
console.error('renewToken error:', err['statusCode']);
}
}
// renewToken()によって得られたトークンでAPI通信
async function setAttribute(token) {
let attributeEndpoint = 'https://api.com/telemetry/'
let options = {
resolveWithFullResponse: true,
uri: attributeEndpoint,
method: 'POST',
headers: {
'Content-type': 'application/json',
'x-authorization': token
},
json: {
"attribute": "test"
}
};
try {
let result = await rp(options);
if (result['statusCode'] !== '200') {
throw 'Status code is not 200';
}
return result;
} catch (err) {
console.error('setAttribute error:', err);
}
}
router.post('/result', function (req, res) {
// トークンを問い合わせ
renewToken().then(token => {
// renewToken()によって得られたトークンでAPI通信
setAttribute(token).then(response => {
res.render(
'result', {
res: response
});
})
})
});
module.exports = router;
Promiseを使ってHTTP通信が可能なrequest-promise-nativeを使用している。
11行目のresolveWithFullResponse: true を定義することで24行目のresultに必要な情報すべてが格納される。
最終的にres.render()によってページを描画しているが、実際的にはここにAPI通信で失敗した場合の処理を加える必要があるだろう。