express 中处理异步异常和超时

参考

express 捕获全局异常的三种方法

如何在 Express4.x 中愉快地使用 async

首先是常见的异常处理中间件。

在异常处理的时候,本人采用了自定义异常的方案,因此可以优先判断是否为自定义异常,如果是则更加优雅的返回错误信息。同时,通过对 res.headersSent 的判断,确保在异常响应之前没有响应客户端,避免 express 报错

import express, { Request, Response, NextFunction } from 'express'
import { HttpError } from '@/models/HttpError'
import { HttpStatusCode } from '@/models/HttpStatusCode'
import { ResponseDto } from '@/models/ResponseDto'
import { IS_DEBUG } from '@/config'
import { Log } from '@/utils'

export function catchError(err: any, req: Request, res: Response, next: NextFunction) {
    let message: any = 'Unknown Error'
    let statusCode = HttpStatusCode.INTERNAL_SERVER_ERROR //500
    if (err instanceof HttpError) {
        message = err.message
        statusCode = err.statusCode
    } else if (err instanceof Error) {
        // 开发阶段打印堆栈信息,否则打印 message
        message = IS_DEBUG ? err.stack : err.message
    } else if (typeof err === 'string') {
        message = err
    }
    if (statusCode >= 500) {
        Log.error(message)
    }
    if (!res.headersSent) { // 若请求还未结束,则回复错误
        res.status(statusCode).json(new ResponseDto({
            statusCode,
            message
        }))
    }
}

接下来是捕获异步异常,这里采用 express-async-errors 这个包

npm install express-async-errors --save

使用

require('express-async-errors') // commonjs 写法
//或
import 'express-async-errors' // es6写法

引入之后就能捕获异步函数中的异常了。

例如

router.get('/async-error', async (req, res, next) => {
    throw new HttpError(500, '服务器出现异步错误') // 该异常会被捕获
})

最后则是超时处理了。

同样的,也要先判断下是否已经响应请求了,若超时未响应,则返回超时异常。和异常捕获结合使用更佳

import express, { Request, Response, NextFunction } from 'express'
import { HttpStatusCode } from '@/models/HttpStatusCode'
import { TIMEOUT } from '@/config'
export async function handleTimeout(req: Request, res: Response, next: NextFunction) {
    const time = TIMEOUT
    // 设置所有HTTP请求的服务器响应超时时间
    res.setTimeout(time, () => {
        const statusCode = HttpStatusCode.REQUEST_TIMEOUT // 409
        if (!res.headersSent) { // 若请求还未结束,则回复超时
            res.status(statusCode).json({
                statusCode,
                message: '请求响应超时'
            })
        }
    })
    next()
}

参考代码:https://github.com/CaoMeiYouRen/express-template


评论

发表回复