【问题标题】:How to catch error in nestjs when a query fails查询失败时如何在nestjs中捕获错误
【发布时间】:2020-07-22 22:53:41
【问题描述】:

我是nestjs 的新手,并试图将我的后端从nodejs 转换为nestjs。希望这有意义吗?我正在使用`typeorm。但我不确定捕捉错误的最佳方法是什么。

entity.ts

import { Entity, Column, PrimaryGeneratedColumn, PrimaryColumn } from 'typeorm';

@Entity()
export class Course {

  @PrimaryColumn()
  course: string;

  @Column("varchar", { array: true })
  subject: string[];
}

controller.ts

import { Controller, Get, Post, Body } from '@nestjs/common';
import { CourseService } from './course.service';
import { Course } from './course.entity';

@Controller('course')
export class CourseController {
    constructor(private courseService: CourseService) {}

    @Get()
    getCourses(): Promise<Course[]> {
        return this.courseService.findAll();
    }

    @Post()
    addCourse(@Body() courseDto: Course[]) {
        return this.courseService.create(courseDto);
    }
}

service.ts

import { Injectable, Catch, ExceptionFilter, ArgumentsHost, ConflictException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, QueryFailedError } from 'typeorm';
import { Course } from './course.entity';

@Injectable()
export class CourseService {
    constructor(
        @InjectRepository(Course)
        private courseRepository: Repository<Course>,
    ) { }

    catch(exception: any, host: ArgumentsHost) {
        throw new Error("Error in course service." + exception.code);
    }

    findAll(): Promise<Course[]> {
        return this.courseRepository.find();
    }

    create(courseDto) {
        return this.courseRepository.insert(courseDto)
            .catch((err: any) => {
                // throw new ConflictException();

                switch (err.name) {
                    case 'QueryFailedError':
                        console.log("**++**" + JSON.stringify(err));
                        // throw new Error("Error" + err.message + "" + err.detail);
                        // throw new ConflictException();
                        throw JSON.stringify(err); //"Error creating a course" + err.message + "::: " + err.detail;
                    default:
                        throw err; 

                }
            });
    }
}

现在,我只能抛出 throw new ConflictException();。我想根据结果抛出不同的错误,比如 - 1.重复记录 2. 缺少必填字段 3.等

但不确定我们如何处理和自定义相同的内容并充分利用nestjs。

就像我在控制台中看到以下跟踪但500, Internal server in postman -

{"message":"duplicate key value violates unique constraint \"PK_d7fc152bc721b3f55a56ed3ad33\"","name":"QueryFailedError","length":293,"severity":"ERROR","code":"23505","detail":"Key (course)=(II) already exists.","schema":"public","table":"course","constraint":"PK_d7fc152bc721b3f55a56ed3ad33","file":"d:\\pginstaller.auto\\postgres.windows-x64\\src\\backend\\access\\nbtree\\nbtinsert.c","line":"535","routine":"_bt_check_unique","query":"INSERT INTO \"course\"(\"course\", \"subject\") VALUES ($1, $2)","parameters":["II",["A","B","C"]]}
[Nest] 12152   - 04/10/2020, 1:18:40 PM   [ExceptionsHandler] {"message":"duplicate key value violates unique constraint \"PK_d7fc152bc721b3f55a56ed3ad33\"","name":"QueryFailedError","length":293,"severity":"ERROR","code":"23505","detail":"Key (course)=(II) already exists.","schema":"public","table":"course","constraint":"PK_d7fc152bc721b3f55a56ed3ad33","file":"d:\\pginstaller.auto\\postgres.windows-x64\\src\\backend\\access\\nbtree\\nbtinsert.c","line":"535","routine":"_bt_check_unique","query":"INSERT INTO \"course\"(\"course\", \"subject\") VALUES ($1, $2)","parameters":["II",["A","B","C"]]} +190924ms

【问题讨论】:

    标签: postgresql nestjs typeorm


    【解决方案1】:

    如何将错误传递给您的控制器并让控制器抛出这些错误。

    service.ts

    create(courseDto) {
      return this.courseRepository.insert(courseDto)
    }
    

    在你的 controller.ts

    import {
      Controller,
      Get,
      Post,
      HttpException,
      HttpStatus,
    } from '@nestjs/common';
    
    ...
    
    @Post()
    async addCourse(@Body() courseDto: Course[]) {
        return await this.courseService.create(courseDto).catch(err => {
          throw new HttpException({
            message: err.message
          }, HttpStatus.BAD_REQUEST);
        })
    }
    

    https://docs.nestjs.com/exception-filters

    【讨论】:

    • 最好让服务处理它,让控制器像你上面提到的那样处理它?
    • 从设计的角度来看,我不支持这个解决方案。在六边形架构中,端点(即控制器)只是访问业务层的一种方式。如果您为您的服务添加 CLI 命令或(停留在 Web 上下文中)GraphQL 解析器,您将需要为每个入口点重新构建所有错误处理。最好让服务层处理对业务至关重要的异常。 IE。当服务需要一个实体来获取/持久化并且它失败时,让它失败。
    • @agoldev 完全同意您的说法,除非它要返回一个特定于 HTTP 的错误(例如带有 HTTP 状态代码)。然后在那种情况下我会接受它(从服务中返回它是不正确的),即使在 Nest.js 中我更愿意看到一个异常过滤器,所以代码最终不会在每个控制器中重复.
    【解决方案2】:

    不要直接返回服务函数,nest 将捕获该异常并假设它来自控制器,另一种解决方案是使用 try/catch 包装

    controller.ts

    try {
      return await this.courseService.create(courseDto)
    } catch (error) {
      // handle error
    }
    
    

    【讨论】:

      猜你喜欢
      • 2019-11-25
      • 2012-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-21
      • 2016-02-14
      • 2021-11-10
      相关资源
      最近更新 更多