我有一个带有一个端点的 Nest api。如果应用程序在 60 秒内没有响应,我想抛出 RequestTimeoutException(),并停止执行所调用的方法而不停止程序本身。我可以向客户端抛出异常,但即使已经抛出异常,应用程序仍会继续执行。
我尝试过以下方法:
@Injectable()
export class TimeoutInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
return next.handle().pipe(
timeout(60000),
catchError((err) => {
if (err instanceof TimeoutError) {
return throwError(() => new RequestTimeoutException());
}
return throwError(() => err);
}),
);
}
}
@Controller('chatbot')
@UseInterceptors(TimeoutInterceptor)
export class ChatbotController {
private readonly chatbotService = new ChatbotService();
@Post('query')
async postQuery(@Body() body: QueryModel) {
if (
!body.chatInfo ||
!body.chatInfo.chatId ||
!body.chatInfo.userId ||
!body.question
)
throw new BadRequestException();
const response = await this.chatbotService.generateResponse(body);
return response;
}
}
@Post('query')
async postQuery(@Body() body: QueryModel) {
let timeoutHandler: NodeJS.Timeout
try {
timeoutHandler = setTimeout(() => {
throw new RequestTimeoutException()
}, 60000)
if (
!body.chatInfo ||
!body.chatInfo.chatId ||
!body.chatInfo.userId ||
!body.question
)
throw new BadRequestException();
const response = await this.chatbotService.generateResponse(body);
clearTimeout(timeoutHandler)
return response;
} catch (error) {
clearTimeout(timeoutHandler)
throw error; // or return error;
}
}
您应该定义一个AbortController并将其传递给generateResponse方法,并在60000秒后中止控制器,它应该是这样的:
@Controller('chatbot')
@UseInterceptors(TimeoutInterceptor)
export class ChatbotController {
private readonly chatbotService = new ChatbotService();
@Post('query')
async postQuery(@Body() body: QueryModel) {
if (!body.chatInfo !body.chatInfo.chatId !body.chatInfo.userId !body.question) {
throw new BadRequestException();
}
const controller = new AbortController();
const signal = controller.signal;
let timeoutHandler: NodeJS.Timeout = setTimeout(() => {
controller.abort();
}, 60000);
try {
const response = await this.chatbotService.generateResponse(body, signal);
clearTimeout(timeoutHandler);
return response;
} catch (error) {
clearTimeout(timeoutHandler);
if (signal.aborted) {
throw new RequestTimeoutException();
}
throw error;
}
}
}
和服务:
@Injectable()
export class ChatbotService {
async generateResponse(body: QueryModel, signal?: AbortSignal): Promise<any> {
if (signal?.aborted) {
throw new RequestTimeoutException();
}
}
}