0
0

[axios] APIのリクエストにインターバルを設ける

Last updated at Posted at 2024-04-05

はじめに

APIのリクエスト処理を作成した際に、ステータスコードが429(Too Many Requests)で返ってきてヒヤっとした経験はないでしょうか?
サードパーティのAPIを利用する場合には、プロバイダがAPIのリクエスト頻度を制限していることが一般的です(例えば、1秒間に10回までなど)
上記の理由で、リクエスト頻度を意識する必要があります

Node.js には、AxiosというHTTPクライアントライブラリがあります

本記事では、Axiosにリクエスト間隔を設定する方法の一例を紹介したいと思います!

ゴール

axiosを使って、APIのリクエスト間隔を制御できる

環境情報

項目 バージョン
Node.js 20.11.1
TypeScript 5.4.3
Axios 1.6.8

方針

以下の方針で実装をしていきます

  • axiosのインスタンス単位でリクエスト間隔を制御する
    • 同一インスタンスを使用して、リクエストする場合にはあらかじめ設定したリクエスト間隔を守ってリクエストを行う
    • 異なるインスタンスでは、それぞれ独立してリクエスト間隔を設定できる
  • axiosのinterceptorsの機能を利用して、リクエストに対して待機処理を追加する
  • axios.createの使用感を維持するため、引数の拡張で対応する

interceptors

axiosには、interceptorsがあります
interceptorsを使用することで、リクエストやレスポンスの処理の前に特定の処理を差し込むことができます

今回は、このinterceptorsを使用して、APIリクエスト前にあらかじめ指定したミリ秒だけ待機するようにします

実装例

以下のフォルダ構成でサンプルを作成してみます

  • project-root/
    • api/
      • sampleApiClient.ts
    • utils/
      • axios.ts
    • index.ts

utils/axios.ts

axios.createを拡張し、リクエスト間隔を調整できるaxiosEx.create を定義します

utils/axios.ts
import axios from "axios";

const createAxiosInstance: CreateAxiosInstance = ({
  interval = 0, 
  ...param
} = {}) => {
  const instance = axios.create(param);

  // 間隔が必ず0ミリ秒以上になるように調整する
  const requestInterval = interval > 0 ? interval : 0;
  
  if (requestInterval > 0) {
    instance.interceptors.request.use(async (config) => {
      await sleep(requestInterval);
      return config;
    });
  }

  return instance;
};

const sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));

// exportして他のファイルから呼び出せるようにする
export const axiosEx = {
  create: createAxiosInstance,
};

// 以下、型定義
type Axios = typeof axios;
type AxiosCreate = Axios["create"];
type AxiosCreateParam = Parameters<AxiosCreate>[0];
type AxiosCreateReturn = ReturnType<AxiosCreate>;

type AxiosExCreateParam = AxiosCreateParam & {
  /**
   * リクエスト間の待機時間 [ms]
   * @default 0
   */
  interval?: number;
};
type AxiosExCreateReturn = AxiosCreateReturn;
type CreateAxiosInstance = (params?: AxiosExCreateParam) => AxiosExCreateReturn;

api/sampleApiClient.ts

axiosEx.create を呼び出して、axiosのインスタンスを用意します
リクエスト間隔を指定するintervalには、500ミリ秒を指定しておきます

api/sampleApiClient.ts
import {axiosEx} from "../utils/axios";

// exportして他のファイルから呼び出せるようにする
export const sampleApiClient = axiosEx.create({
  baseURL: "http://localhost:3000",
  interval: 500, // [ms]
});

index.ts

sampleApiClient を呼び出します

index.ts
import {sampleApiClient} from "./api/sampleApiClient";

const main = async () => {
  const names = [
    "Noby",
    "Sue",
    "Big G",
    "Sneech",
    "Doraemon",
  ];

  // 配列の処理が非同期で行われないように、呼び出し側で要注意
  for (const name of names) {
    // 500ms待ってから、APIリクエストを行う
    const { data } = await sampleApiClient.get<string>("/api/hello", {
      params: { name },
    }).catch((error) => {
      console.error(error);
      throw error;
    });
    console.log(data); // e.g. Hello, Noby!
  }
};

main();

まとめ

今回は、axiosで簡易的にリクエスト間隔を調整する方法を紹介しました
(別の方法としてaxiosのインスタンスをステートフルにしてタイムスタンプを管理するようにしたら、より厳密にリクエスト間隔を調整できそうな気がします)

理想を言えば、axiosが公式にAPIのリクエストの間隔を設定できるようなアップデートがあると嬉しいです

↓ 今回試した内容はGithubに公開しています。よければ参考にしてください

参考

0
0
0

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