Was ist der Fehlerbehandlungsansatz von nestjs (Geschäftslogikfehler vs. HTTP-Fehler)?
Lesezeit: 4 Minuten
Aaron Ullal
Bei der Verwendung von NestJS zum Erstellen von APIs habe ich mich gefragt, wie Fehler/Ausnahmen am besten behandelt werden. Ich habe zwei verschiedene Ansätze gefunden:
Haben Sie individuelle Dienste und Validierungsrohre throw new Error()haben den Controller catch sie und werfen Sie dann die entsprechende Art von HttpException(BadRequestException, ForbiddenException usw..)
Lassen Sie den Controller einfach die Dienst-/Validierungs-Pipe-Methode aufrufen, die für die Handhabung dieses Teils der Geschäftslogik verantwortlich ist, und lösen Sie die entsprechende aus HttpException.
Beide Ansätze haben Vor- und Nachteile:
Dies scheint der richtige Weg zu sein, der Dienst kann jedoch zurückkehren Error Aus verschiedenen Gründen, woher weiß ich vom Controller, welches die entsprechende Art von wäre HttpException zurückgeben?
Sehr flexibel, aber mit Http verwandte Dinge in den Diensten scheinen einfach falsch zu sein.
Ich habe mich gefragt, welches (falls vorhanden) die “nest js” -Methode ist?
Wie gehen Sie mit dieser Angelegenheit um?
Kim Kern
Nehmen wir an, Ihre Geschäftslogik löst ein aus EntityNotFoundError und Sie möchten es a zuordnen NotFoundException.
Dafür können Sie eine erstellen Interceptor das verwandelt deine Fehler:
@Injectable()
export class NotFoundInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
// next.handle() is an Observable of the controller's result value
return next.handle()
.pipe(catchError(error => {
if (error instanceof EntityNotFoundError) {
throw new NotFoundException(error.message);
} else {
throw error;
}
}));
}
}
Sie können es dann verwenden, indem Sie es hinzufügen @UseInterceptors(NotFoundInterceptor) an die Klasse oder Methoden Ihres Controllers; oder sogar als globaler Abfangjäger für alle Routen. Natürlich können Sie auch mehrere Fehler in einem Interceptor abbilden.
Nest Js bietet einen Ausnahmefilter, der Fehler behandelt, die nicht in der Anwendungsschicht behandelt werden. Daher habe ich ihn so geändert, dass er 500, einen internen Serverfehler, für Ausnahmen zurückgibt, die nicht Http sind. Dann protokollieren Sie die Ausnahme auf dem Server, dann können Sie wissen, was falsch ist, und es beheben.
Schöne Umsetzung! Ich denke, Sie können auch die NestJS-Abhängigkeitsinjektionssyntax verwenden, sodass Sie keine private Eigenschaft “Logger” deklarieren und dann instanziieren müssen. Sie können einfach “private readonly logger : Logger” im Konstruktor verwenden und es wird automatisch instanziiert.
– Marcus Castanho
6. Januar 2022 um 14:25 Uhr
Vielen Dank, notiert wird die Antwort implementieren und aktualisieren.
– Ukpa Uchechi
6. Januar 2022 um 14:34 Uhr
Zumindest für meinen Anwendungsfall ist dies die beste Antwort.
– noamtm
15. Mai 2022 um 13:53 Uhr
FYI @MarcusCastanho – es scheint, dass Sie NestJS DI nicht verwenden können, zumindest wenn Sie einen globalen Filter verwenden – weil Sie den Filter selbst instanziieren müssen.
– noamtm
15. Mai 2022 um 13:54 Uhr
Um die richtige Fehlermeldung zurückzugeben, müssen Sie Folgendes tun: const message = exception instanceof HttpException ? exception.getResponse()?.['message'] ? exception.getResponse()?.['message'] : exception['message'] : 'Internal server error';
– Lukas Vellido
9. Juni 2022 um 15:08 Uhr
Möglicherweise möchten Sie Dienste nicht nur an die HTTP-Schnittstelle, sondern auch an GraphQL oder eine andere Schnittstelle binden. Daher ist es besser, Ausnahmen auf Geschäftslogikebene von Diensten in Ausnahmen auf HTTP-Ebene (BadRequestException, ForbiddenException) in Controllern umzuwandeln.
So könnte es im einfachsten Fall aussehen
import { BadRequestException, Injectable } from '@nestjs/common';
@Injectable()
export class HttpHelperService {
async transformExceptions(action: Promise<any>): Promise<any> {
try {
return await action;
} catch (error) {
if (error.name === 'QueryFailedError') {
if (/^duplicate key value violates unique constraint/.test(error.message)) {
throw new BadRequestException(error.detail);
} else if (/violates foreign key constraint/.test(error.message)) {
throw new BadRequestException(error.detail);
} else {
throw error;
}
} else {
throw error;
}
}
}
}
und dann
Danke Alex. Wie würden Sie den von Ihnen geposteten Code verwenden? Im Steuergerät?
– Aaron Ullal
13. August 2018 um 16:07 Uhr
Wie haben Sie diesen Dienst implementiert?
– Lewsmith
9. Februar 2020 um 16:47 Uhr
Dario Palmino
Sie können auch eine Factory oder einen Handler verwenden, um, wenn der Controller die Ausnahme (Fehler oder Domänenfehler) abfängt, diese einer anderen HttpException zuzuordnen.
@Controller('example')
export class ExampleController {
@Post('make')
async make(@Res() res, @Body() data: dataDTO): Promise<any> {
try {
//process result...
return res.status(HttpStatus.OK).json(result);
} catch (error) {
throw AppErrorHandler.createHttpException(error); //<---here is the error type mapping
};
};
};
14418300cookie-checkWas ist der Fehlerbehandlungsansatz von nestjs (Geschäftslogikfehler vs. HTTP-Fehler)?yes