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

NestJS如何在onApplicationBootstrap及定时任务中全局处理错误?

非Controller场景的全局错误处理方案

Nest的全局异常过滤器、拦截器默认只作用于HTTP请求链路(也就是Controller处理请求的上下文),像onApplicationBootstrap启动钩子、@Cron定时任务这类脱离HTTP请求的场景,自然无法触发默认的全局异常处理逻辑。下面是几种可行的解决方式:

1. 自定义全局错误处理服务 + 手动捕获

这是最通用的方案,不管是启动钩子还是定时任务都适用:

步骤1:创建全局错误处理服务

import { Injectable, Logger } from '@nestjs/common';
import { HttpException } from '@nestjs/common';

@Injectable()
export class ErrorHandlingService {
  private readonly logger = new Logger(ErrorHandlingService.name);

  handleError(exception: unknown) {
    // 可根据异常类型做差异化处理:日志记录、告警推送、数据回滚等
    if (exception instanceof HttpException) {
      this.logger.error(`业务异常: ${exception.message}`, exception.stack);
      // 示例:调用告警接口
      // await this.alertService.sendAlert(exception.getStatus(), exception.message);
    } else {
      this.logger.error(`未知异常`, exception.stack);
    }
  }
}

步骤2:在调用处手动捕获异常并处理

在TasksService中注入错误处理服务,用try/catch包裹可能抛出异常的方法调用:

import { Injectable, OnApplicationBootstrap } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { TowerService } from './tower.service';
import { ErrorHandlingService } from './error-handling.service';

@Injectable()
export class TasksService implements OnApplicationBootstrap {
  constructor(
    private readonly towerService: TowerService,
    private readonly errorHandlingService: ErrorHandlingService,
  ) {}

  async onApplicationBootstrap() {
    try {
      await this.towerService.sendTowerJob();
    } catch (e) {
      this.errorHandlingService.handleError(e);
    }
  }

  @Cron(CronExpression.EVERY_HOUR)
  async scheduledTowerJob() {
    try {
      await this.towerService.sendTowerJob();
    } catch (e) {
      this.errorHandlingService.handleError(e);
    }
  }
}

2. 复用现有全局异常过滤器(适配非HTTP场景)

如果已经有现成的全局异常过滤器,不想重复写处理逻辑,可以手动调用过滤器的catch方法,但需要先调整过滤器逻辑,让它兼容无HTTP上下文的场景:

调整全局过滤器逻辑

import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';

@Catch(HttpException)
export class GlobalHttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host?: ArgumentsHost) {
    // 处理HTTP请求场景
    if (host) {
      const ctx = host.switchToHttp();
      const response = ctx.getResponse();
      const status = exception.getStatus();
      response.status(status).json({
        statusCode: status,
        message: exception.message,
      });
    } else {
      // 处理非HTTP场景(启动钩子、定时任务)
      console.error('非HTTP场景捕获异常:', exception.message, exception.stack);
      // 可复用错误处理逻辑,比如调用ErrorHandlingService
    }
  }
}

在调用处手动调用过滤器

import { Injectable, OnApplicationBootstrap } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { TowerService } from './tower.service';
import { GlobalHttpExceptionFilter } from './global-http-exception.filter';

@Injectable()
export class TasksService implements OnApplicationBootstrap {
  constructor(
    private readonly towerService: TowerService,
    private readonly globalFilter: GlobalHttpExceptionFilter,
  ) {}

  async onApplicationBootstrap() {
    try {
      await this.towerService.sendTowerJob();
    } catch (e) {
      this.globalFilter.catch(e); // 不传host,触发非HTTP场景逻辑
    }
  }
}

3. 定时任务专属全局错误处理

Nest的定时任务模块提供了全局错误处理配置,直接在ScheduleModule初始化时配置即可,无需每个任务都写try/catch:

import { Module } from '@nestjs/common';
import { ScheduleModule } from '@nestjs/schedule';
import { TasksService } from './tasks.service';
import { ErrorHandlingService } from './error-handling.service';

@Module({
  imports: [
    ScheduleModule.forRoot({
      errorHandler: (err) => {
        // 统一处理所有定时任务的异常
        const errorHandler = new ErrorHandlingService();
        errorHandler.handleError(err);
        // 若ErrorHandlingService为全局服务,可通过依赖注入获取(此处为简化示例)
      },
    }),
  ],
  providers: [TasksService, ErrorHandlingService],
})
export class TasksModule {}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 10:05:30