0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

個人的アドカレAdvent Calendar 2024

Day 17

Promise.allを使用したAPI並列処理の実装と処理時間の改善

Last updated at Posted at 2024-12-18

はじめに

複数のAPIを呼び出す必要がある場合、直列的に処理を行うとそれらの処理時間が各APIの処理時間の合計になってしまいます。本記事では、Promise.allを使用して複数のAPIを並列で呼び出し、全体の処理時間を短縮する処理を実装します。

現状

  • API A(2秒)とAPI B(3秒)を順番に呼び出すと、合計5秒かかる
  • APIの実行順序に依存関係がない

モックAPI

検証用にコールするモックAPIを2つ作成します。

  1. API A (/api/check)

    • 処理時間: 2秒
    • レスポンス: { isAvailable: boolean }
  2. 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

image.png

ボタンをクリックして処理時間を確認してみます。

  • 直列処理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秒

image.png

  • 並列処理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秒

image.png

APIを直列的に呼び出した場合と並列で呼び出した場合で、処理時間に明確な差が出ることを確認できました。

参考

0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?