异常处理

未匹配的标注

AdonisJS 使用异常进行流控制。这意味着,我们宁愿引发异常,然后处理它们以返回适当的响应,而不是编写太多的条件。例如:

我们更喜欢这样写代码

在以下示例中,如果用户未登录,auth.authenticate 方法将引发异常。异常可以自行处理并返回适当的响应。

Route.get('dashboard', async ({ auth, response }) => {
  await auth.authenticate()

  // 业务逻辑
})

提示:不要将所有不符合要求的条件都转化为异常,建议只转换那些会导致请求中止的条件。

而不是编写以下代码

Route.get('dashboard', async ({ auth, response }) => {
  if (!auth.isLoggedIn) {
    return response.status(401).send('Unauthenticated')
  }

  // 业务逻辑
})

全局处理异常

HTTP请求期间引发的异常被转发到存储在 app/Exceptions/Handler.ts 文件中。

// app/Exceptions/Handler.ts 文件
import Logger from '@ioc:Adonis/Core/Logger'
import HttpExceptionHandler from '@ioc:Adonis/Core/HttpExceptionHandler'

export default class ExceptionHandler extends HttpExceptionHandler {
  protected statusPages = {
    '404': 'errors/not-found',
    '500..599': 'errors/server-error',
  }

  constructor() {
    super(Logger)
  }
}

handle 方法负责处理异常并将其转换为响应。 因此,可以让父类 (HttpExceptionHandler) 来处理错误, 或者自定义 handle 方法来处理这些错误。

import Logger from '@ioc:Adonis/Core/Logger'
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import HttpExceptionHandler from '@ioc:Adonis/Core/HttpExceptionHandler'

export default class ExceptionHandler extends HttpExceptionHandler {
  protected statusPages = {
    '404': 'errors/not-found',
    '500..599': 'errors/server-error',
  }

  constructor() {
    super(Logger)
  }

  public async handle(error: any, ctx: HttpContextContract) {
    /**
     * 自行处理验证异常
     */
    if (error.code === 'E_VALIDATION_FAILURE') {
      return ctx.response.status(422).send(error.messages)
    }

    /**
     * 将其余异常转发给父类
     */
    return super.handle(error, ctx)
  }
}

错误报告

除了 handle 方法,您还可以实现report 方法来将异常报告给日志记录或错误监控服务。

report方法的默认实现使用 logger 来报告异常。

  • 使用logger.error方法记录错误代码>= 500的异常。
  • 使用logger.warn方法记录错误代码为>= 400的异常。
  • 使用logger.info方法记录所有其他异常。

注:HTTP 响应不等待报告方法完成。也就是说,report 方法是在后台执行的。

如果需要,您可以覆盖report方法,如下例所示。

import Logger from '@ioc:Adonis/Core/Logger'
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import HttpExceptionHandler from '@ioc:Adonis/Core/HttpExceptionHandler'

export default class ExceptionHandler extends HttpExceptionHandler {
  protected statusPages = {
    '404': 'errors/not-found',
    '500..599': 'errors/server-error',
  }

  constructor() {
    super(Logger)
  }

  // highlight-start
  public async report(error: any, ctx: HttpContextContract) {
    if (!this.shouldReport(error)) {
      return
    }

   if (typeof error.report === 'function') {
      error.report(error, ctx)
      return
    }

    someReportingService.report(error.message)
  }
  // highlight-end
}

报告上下文

可以实现context方法以在报告错误时提供额外的数据。默认情况下,上下文包括当前请求 ID。

import Logger from '@ioc:Adonis/Core/Logger'
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import HttpExceptionHandler from '@ioc:Adonis/Core/HttpExceptionHandler'

export default class ExceptionHandler extends HttpExceptionHandler {
  protected context(ctx: HttpContextContract) {
    return {
      userId: ctx.auth.user?.id
    }
  }
}

HTTP 异常处理程序

以下功能仅在全局异常处理程序扩展 HttpExceptionHandler 类时可用。如果你决定不从此类扩展,则以下功能将不起作用。

页面状态

异常处理程序上的statusPages页面属性允许将 Edge 模板与一系列错误状态代码相关联。

在以下示例中,所有 404 错误将呈现errors/not-found.edge模板,500 - 599范围内的错误将呈现errors/server-error.edge模板。

import Logger from '@ioc:Adonis/Core/Logger'
import HttpExceptionHandler from '@ioc:Adonis/Core/HttpExceptionHandler'

export default class ExceptionHandler extends HttpExceptionHandler {
  // highlight-start
  protected statusPages = {
    '404': 'errors/not-found',
    '500..599': 'errors/server-error',
  }
  // highlight-end

  constructor() {
    super(Logger)
  }
}
  • 仅当 HTTP 请求Accept未设置为application/json时,才会呈现状态页面。

  • T状态页面在开发过程中被禁用。但是,您可以使用disableStatusPagesInDevelopment标志来启用它们。

    export default class ExceptionHandler extends HttpExceptionHandler {
    protected disableStatusPagesInDevelopment = false
    }

禁用某些异常的报告

您可以通过将某些异常添加到ignoreCodesignoreStatuses属性中来忽略报告的某些异常。

import Logger from '@ioc:Adonis/Core/Logger'
import HttpExceptionHandler from '@ioc:Adonis/Core/HttpExceptionHandler'

export default class ExceptionHandler extends HttpExceptionHandler {
  // highlight-start
  protected ignoreCodes = ['E_ROUTE_NOT_FOUND']
  protected ignoreStatuses = [404, 422, 403, 401]
  // highlight-end

  constructor() {
    super(Logger)
  }
}

自定义异常

可以通过执行以下 Ace 命令来创建自定义异常。

node ace make:exception UnAuthorized
# 创建: app/Exceptions/UnAuthorizedException.ts

接下来,导入并引发异常,如下所示。

import UnAuthorized from 'App/Exceptions/UnAuthorizedException'

const message = 'You are not authorized'
const status = 403
const errorCode = 'E_UNAUTHORIZED'

throw new UnAuthorized(message, status, errorCode)

你可以通过在异常类上实现 handle 方法来自行处理此异常。

// app/Exceptions/UnAuthorizedException.ts 文件
import { Exception } from '@adonisjs/core/build/standalone'
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'

export default class UnAuthorizedException extends Exception {
  public async handle(error: this, ctx: HttpContextContract) {
    ctx.response.status(error.status).send(error.message)
  }
}

或者,你可以实现 report 方法将异常记录到日志,或错误报告服务。

// app/Exceptions/UnAuthorizedException.ts 文件
import { Exception } from '@adonisjs/core/build/standalone'
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'

export default class UnAuthorizedException extends Exception {
  public report(error: this, ctx: HttpContextContract) {
    reportingService.report(error.message)
  }
}

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://learnku.com/docs/adonisjs/5.x/ht...

译文地址:https://learnku.com/docs/adonisjs/5.x/ht...

上一篇 下一篇
贡献者:4
讨论数量: 0
发起讨论 只看当前版本


暂无话题~