You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular应用中如何区分并设置写入/读取/连接超时?

Angular中区分三类请求超时场景的实现方案

现有拦截器仅能处理整体请求超时,无法区分连接、写入、读取阶段的超时差异。要实现细分场景的超时检测,可通过自定义拦截器结合RxJS操作符,针对不同请求阶段做针对性超时控制:

1. 连接超时(Connection Timeout)

连接超时指无法在指定时间内与目标服务器建立TCP连接。可通过race操作符,将请求Observable与一个延迟超时的Observable绑定,若在指定时间内未收到HttpSentEvent(请求已发送的标记),则判定为连接超时。

2. 写入超时(Write Timeout)

写入超时指请求数据发送至服务器的过程耗时过久(如大文件上传时网络卡顿)。可在收到HttpSentEvent后启动独立超时计时器,若在指定时间内未收到HttpResponseHeaderEvent(服务器已响应头部的标记),则判定为写入超时。

3. 读取超时(Read Timeout)

读取超时指服务器开始返回数据后,后续数据块的间隔过长。可在收到第一个响应数据事件后,重置超时计时器,用timeout操作符监控每个数据块的间隔时间,若超过阈值则判定为读取超时。

整合三类场景的拦截器实现

import { Injectable } from '@angular/core';
import {
  HttpInterceptor,
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpSentEvent,
  HttpResponseHeaderEvent,
  HttpErrorResponse
} from '@angular/common/http';
import { Observable, throwError, race, timer } from 'rxjs';
import { catchError, switchMap, timeout } from 'rxjs/operators';
import { TimeoutError } from 'rxjs';
import { environment } from '../environments/environment';

@Injectable()
export class RequestStageTimeoutInterceptor implements HttpInterceptor {
  // 配置各阶段超时阈值
  private readonly connectionTimeout = environment.connectionTimeout || 5000;
  private readonly writeTimeout = environment.writeTimeout || 10000;
  private readonly readTimeout = environment.readTimeout || 15000;

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    // 连接阶段超时:未发送则触发超时
    const connectionTimeout$ = timer(this.connectionTimeout).pipe(
      switchMap(() => throwError(() => new HttpErrorResponse({
        error: 'Connection Timeout',
        status: 0,
        statusText: 'Connection Timeout'
      })))
    );

    return race(next.handle(request), connectionTimeout$).pipe(
      switchMap(event => {
        if (event instanceof HttpSentEvent) {
          // 进入写入阶段:监控到响应头部前的超时
          return next.handle(request).pipe(
            timeout(this.writeTimeout),
            catchError(error => this.handleTimeoutError(error, 'Write Timeout'))
          );
        } else if (event instanceof HttpResponseHeaderEvent) {
          // 进入读取阶段:监控数据块间隔超时
          return next.handle(request).pipe(
            timeout(this.readTimeout),
            catchError(error => this.handleTimeoutError(error, 'Read Timeout'))
          );
        }
        return [event];
      }),
      catchError(error => {
        // 统一处理非HttpErrorResponse类型错误
        if (!(error instanceof HttpErrorResponse)) {
          return throwError(() => new HttpErrorResponse({
            error: 'Unknown Request Error',
            status: 500,
            statusText: 'Internal Error'
          }));
        }
        return throwError(() => error);
      })
    );
  }

  private handleTimeoutError(error: unknown, timeoutType: string): Observable<never> {
    if (error instanceof TimeoutError) {
      return throwError(() => new HttpErrorResponse({
        error: timeoutType,
        status: 408,
        statusText: timeoutType
      }));
    }
    return throwError(() => error);
  }
}

关键说明

  • 各阶段超时阈值可通过environment配置,便于不同环境切换
  • 利用Angular的HttpEvent类型区分请求阶段:
    • HttpSentEvent:请求已发出,进入写入阶段
    • HttpResponseHeaderEvent:服务器返回响应头部,进入读取阶段
  • 通过RxJS的race、timeout、switchMap操作符实现分阶段超时控制

内容的提问来源于stack exchange,提问作者Czeran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 21:22:19