noxi雑記

.NET、Angularまわりの小ネタブログ

AngularのHTTPインターセプターで同時HTTPリクエスト数を制限する

AngularのHTTPインターセプターと非同期ロック処理を組み合わせると、とても無駄な感じもしますが、AJAXリクエストの同時リクエスト数を制限することができます。ブラウザが同時に6本までしか送らないのでぶっちゃけ無駄な気もしますが、有用なこともあるでしょう。。。


非同期ロックライブラリのインストール

今回は await-semaphore を使用します。 npm i -P await-semaphore を実行してインストールします。

HTTPインターセプターの実装

非同期ロックを実行しつつ次の処理を実行するとこんな感じになります。 Semaphoreコンストラクターに渡す数値で同時実行数が制限されます。キモは finalize オペレーターを使用してHTTPリクエスト終了時にセマフォを解放することです。

import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Semaphore } from 'await-semaphore';
import { from, Observable } from 'rxjs';
import { finalize, switchMap } from 'rxjs/operators';

/**
 * HTTPリクエストの同時処理数を制限するHTTPインターセプター
 */
@Injectable()
export class SequentialRequestHttpInterceptor implements HttpInterceptor {

  private readonly semaphore = new Semaphore(1);

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return from(this.acquire()).pipe(
      switchMap(release => next.handle(req).pipe(finalize(() => release()))),
    );
  }

  private async acquire() {
    return await this.semaphore.acquire();
  }

}