Nest.js 应用程序在没有等待的异步函数中抛出错误后变得无响应

akr*_*acs 5 nestjs

问题是,如果函数中抛出异常async,但在没有 的情况下调用该函数await,则 Nest 应用程序将进入不再响应请求但进程不存在的状态。

有时我们可能想在请求中调用一个函数,但不需要等待它完成后再返回对调用者的响应,但大多数时候我们遇到这种情况只是意外遗漏了await. 事实上,它使服务器变得无用,这是一个很大的问题。

我怀疑这个问题可能有一个简单的解决方案,但我自己没有成功找到它。

应用程序控制器.ts

import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }

  @Get('/crash')
  public async crash(): Promise<void> {
    await this.appService.crash();
  }
}
Run Code Online (Sandbox Code Playgroud)

应用程序服务.ts

import { Injectable } from '@nestjs/common';

const sleep = async (ms: number): Promise<void> => {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
};

const functionThatThrows = async (): Promise<void> => {
  await sleep(2000);
  throw new Error('this will crash the app');
};

@Injectable()
export class AppService {
  getHello(): string {
    return 'Hello World!';
  }

  public async crash(): Promise<void> {
    console.log('crashing the app in 3 seconds...');
    await sleep(1000);
    functionThatThrows(); // async function called without await
  }
}
Run Code Online (Sandbox Code Playgroud)

第一次调用端点成功:

curl http://localhost:3000/crash

之后调用,服务器没有响应:

curl http://localhost:3000/crash

curl: (7) Failed to connect to localhost port 3000 after 5 ms: Connection refused

Jay*_*iel 8

这是因为节点因未处理的承诺拒绝而崩溃。Nest 的异常过滤器将捕获请求期间发生的错误,但如果错误发生在请求之外(例如没有 的 Promise/async 函数)await,则只有标准 Node 错误处理程序处于活动状态。你需要一个process.on('unhandledRejection', errorHandler)来防止进程崩溃

  • @Craques实际上因为promise不是“await”的,所以他们必须在promise上使用“.catch” (2认同)