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

Nest.js中如何在超时后终止请求处理?

在Nest.js中实现超时后终止请求处理的方案

官方的TimeoutInterceptor仅负责向客户端返回超时错误,但不会终止服务端的请求处理流程。要实现超时后自动取消后续操作,可以结合AbortController(Node.js 16+原生支持,低版本可安装abort-controller包)来传递取消信号,让异步操作能响应超时事件。

1. 自定义可取消的超时拦截器

替换官方拦截器,在超时触发时发送取消信号:

import { Injectable, NestInterceptor, ExecutionContext, CallHandler, RequestTimeoutException } from '@nestjs/common';
import { Observable, throwError, TimeoutError } from 'rxjs';
import { catchError, timeout } from 'rxjs/operators';
import { AbortController } from 'abort-controller'; // Node <16 需安装此包

@Injectable()
export class CancelableTimeoutInterceptor implements NestInterceptor {
  constructor(private readonly timeoutMs: number) {}

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const abortController = new AbortController();
    const request = context.switchToHttp().getRequest();
    // 将取消信号挂载到请求对象
    request.abortSignal = abortController.signal;

    return next.handle().pipe(
      timeout(this.timeoutMs),
      catchError((err) => {
        if (err instanceof TimeoutError) {
          // 触发取消信号,通知处理器终止操作
          abortController.abort();
          return throwError(() => new RequestTimeoutException());
        }
        return throwError(() => err);
      }),
    );
  }
}

2. 全局注册拦截器

在根模块中注册拦截器,设置全局超时时间:

import { Module } from '@nestjs/common';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { CancelableTimeoutInterceptor } from './cancelable-timeout.interceptor';

@Module({
  providers: [
    {
      provide: APP_INTERCEPTOR,
      useValue: new CancelableTimeoutInterceptor(5000), // 设定5秒超时
    },
  ],
})
export class AppModule {}

3. 在处理器中响应取消信号

根据使用的异步操作类型,将abortSignal传入对应方法,实现自动取消:

示例1:Axios请求

import { Controller, Get, Req } from '@nestjs/common';
import axios from 'axios';

@Controller('external')
export class ExternalController {
  @Get()
  async fetchExternalData(@Req() req) {
    try {
      // 将取消信号传给axios,超时后自动终止请求
      const response = await axios.get('https://example.com/large-dataset', {
        signal: req.abortSignal,
      });
      return response.data;
    } catch (err) {
      // 捕获取消错误,无需向上抛出
      if (err.name === 'AbortError') return;
      throw err;
    }
  }
}

示例2:自定义异步任务

手动监听取消信号,清理资源:

import { Controller, Get, Req } from '@nestjs/common';

async function longRunningTask(signal: AbortSignal) {
  return new Promise((resolve, reject) => {
    const timer = setTimeout(() => resolve('task completed'), 10000);
    
    // 监听取消信号,清理定时器并终止任务
    signal.addEventListener('abort', () => {
      clearTimeout(timer);
      reject(new Error('task aborted due to timeout'));
    });
  });
}

@Controller('tasks')
export class TaskController {
  @Get('long')
  async runLongTask(@Req() req) {
    try {
      return await longRunningTask(req.abortSignal);
    } catch (err) {
      if (err.message.includes('aborted')) return;
      throw err;
    }
  }
}

示例3:TypeORM数据库操作

通过QueryRunner监听取消信号,释放数据库连接:

import { Controller, Get, Req } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './user.entity';

@Controller('users')
export class UserController {
  constructor(@InjectRepository(User) private userRepo: Repository<User>) {}

  @Get()
  async getUsers(@Req() req) {
    const queryRunner = this.userRepo.manager.connection.createQueryRunner();
    try {
      await queryRunner.connect();
      
      // 超时取消时释放连接
      req.abortSignal.addEventListener('abort', () => {
        queryRunner.release();
      });

      const users = await queryRunner.manager.find(User);
      return users;
    } catch (err) {
      if (err.name === 'AbortError') return;
      throw err;
    } finally {
      // 未取消时正常释放连接
      if (!req.abortSignal.aborted) {
        await queryRunner.release();
      }
    }
  }
}

核心优势

  • 无需在每个处理器中手动检查超时状态,通过信号传递实现自动取消
  • 符合Node.js异步取消的标准规范,兼容性好
  • 能自动清理资源(定时器、数据库连接、HTTP请求等),避免内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 20:15:43