はじめに
複数のAPIを呼び出す必要がある場合、直列的に処理を行うとそれらの処理時間が各APIの処理時間の合計になってしまいます。本記事では、Promise.all
を使用して複数のAPIを並列で呼び出し、全体の処理時間を短縮する処理を実装します。
現状
- API A(2秒)とAPI B(3秒)を順番に呼び出すと、合計5秒かかる
- APIの実行順序に依存関係がない
モックAPI
検証用にコールするモックAPIを2つ作成します。
-
API A (
/api/check
)- 処理時間: 2秒
- レスポンス:
{ isAvailable: boolean }
-
API B (
/api/process
)- 処理時間: 3秒
- レスポンス:
{ message: "hogeMessage" }
環境
- express:4.21.2
- cors:2.8.5
構成
├─backend
│ server.js
│
└─frontend
index.css
index.html
index.js
ゴール
2つのAPIを並列で呼び出し、処理時間を5秒から3秒に改善する。
モックAPIを作成
フロントからコールするためのモックAPIを準備します。
index.js
const express = require('express');
const app = express();
const cors = require('cors');
app.use(cors());
// API A:(2秒)
app.get('/api/check', (req, res) => {
setTimeout(() => {
res.json({
isAvailable: true
});
}, 2000);
});
// API B: (3秒)
app.get('/api/process', (req, res) => {
setTimeout(() => {
res.json({
message: "hogeMessage"
});
}, 3000);
});
const port = 8000;
app.listen(port, () => {
console.log(`Server running on http://localhost:${port}`);
});
フロントエンド実装
HTML
ボタンをクリックすることで、APIの呼び出しを実行できる簡単なUIを実装します。
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>API並列処理デモ</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<div class="container">
<button id="actionButton">APIコール</button>
<div id="loading" class="loading">処理中...</div>
<div id="timer" class="timer"></div>
</div>
<script src="index.js"></script>
</body>
</html>
index.css
index.css
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
}
.container {
text-align: center;
}
button {
padding: 10px 20px;
cursor: pointer;
}
.loading {
display: none;
margin-top: 10px;
}
.loading.show {
display: block;
}
.timer {
margin-top: 10px;
}
APIコールするスクリプト
直列的にAPIコールする場合
index.js
const button = document.getElementById('actionButton');
const loading = document.getElementById('loading');
async function handleClickSequential() {
const startTime = performance.now();
button.disabled = true;
loading.classList.add('show');
// 直列的にAPIコール
const responseA = await fetch('http://localhost:8000/api/check');
const resultA = await responseA.json();
const responseB = await fetch('http://localhost:8000/api/process');
const resultB = await responseB.json();
button.disabled = false;
loading.classList.remove('show');
const endTime = performance.now();
const processedTime = `処理時間: ${((endTime - startTime) / 1000).toFixed(2)}秒`;
// 実行結果
console.log('API A結果:', resultA);
console.log('API B結果:', resultB);
console.log(processedTime);
}
並行でAPIコールする場合
index.js
async function handleClickParallel() {
const startTime = performance.now();
button.disabled = true;
loading.classList.add('show');
// 並列にAPIコール
const [resultA, resultB] = await Promise.all([
fetch('http://localhost:8000/api/check').then(res => res.json()),
fetch('http://localhost:8000/api/process').then(res => res.json())
]);
button.disabled = false;
loading.classList.remove('show');
const endTime = performance.now();
const processedTime = `処理時間: ${((endTime - startTime) / 1000).toFixed(2)}秒`;
// 実行結果
console.log(processedTime);
console.log('API A結果:', resultA);
console.log('API B結果:', resultB);
}
動作確認
本記事では live-server
でWebサーバを立てます。
バックエンドのモックAPIは下記のコマンドでサーバを起動しておきます。
node server.js
Server running on http://localhost:8000
ボタンをクリックして処理時間を確認してみます。
-
直列処理ver:
約5秒(2秒 + 3秒)
response
Live reload enabled.
index.js:39 API A結果: {isAvailable: true}
index.js:40 API B結果: {message: 'hogeMessage'}
index.js:46 処理時間: 5.03秒
-
並列処理ver:
約3秒
response
Live reload enabled.
index.js:16 API A結果: {isAvailable: true}
index.js:17 API B結果: {message: 'hogeMessage'}
index.js:23 処理時間: 3.00秒
APIを直列的に呼び出した場合と並列で呼び出した場合で、処理時間に明確な差が出ることを確認できました。