03

    科技2026-02-03  3

    03_koa异常处理

    一.全局异常处理中间件

    全局异常处理的中间件需满足两个条件:

    必须作为第一个中间件被注册

    在next函数被调用时,使用 try-catch 即可全局捕获到异常

    const catchError = async (ctx, next) => { try { await next() } catch(error) { ctx.body = "服务器出错了" } } module.exports = catchError const Koa = require('koa') const Router = require('koa-router') const catchError = require('./exception/exception') const app = new Koa() const router = new Router() router.get('/api/v1/other/exception', async (ctx, next) => { throw new Error() }) app.use(catchError) app.use(router.routes()) .use(router.allowedMethods()) app.listen(3000)

    二.定义错误返回格式

    在程序里捕捉到的error,不应该直接返回到客户端,而需要将error进行简化,返回给前端清晰明了的错误信息 我们应该返回给前端哪些信息:

    HTTP Status Code: http状态码,2xx、4xx、5xx

    100 “continue”101 “switching protocols”102 “processing”200 “ok”201 “created”202 “accepted”203 “non-authoritative information”204 “no content”205 “reset content”206 “partial content”207 “multi-status”208 “already reported”226 “im used”300 “multiple choices”301 “moved permanently”302 “found”303 “see other”304 “not modified”305 “use proxy”307 “temporary redirect”308 “permanent redirect”400 “bad request”401 “unauthorized”402 “payment required”403 “forbidden”404 “not found”405 “method not allowed”406 “not acceptable”407 “proxy authentication required”408 “request timeout”409 “conflict”410 “gone”411 “length required”412 “precondition failed”413 “payload too large”414 “uri too long”415 “unsupported media type”416 “range not satisfiable”417 “expectation failed”418 “I’m a teapot”422 “unprocessable entity”423 “locked”424 “failed dependency”426 “upgrade required”428 “precondition required”429 “too many requests”431 “request header fields too large”500 “internal server error”501 “not implemented”502 “bad gateway”503 “service unavailable”504 “gateway timeout”505 “http version not supported”506 “variant also negotiates”507 “insufficient storage”508 “loop detected”510 “not extended”511 “network authentication required”

    message: 文字化的错误信息

    errorCode: 开发者自己定义,10001、10002…

    requestUrl: 当前请求的url

    const Koa = require('koa') const Router = require('koa-router') const catchError = require('./exception/exception') const app = new Koa() const router = new Router() router.get('/api/v1/other/exception', async (ctx, next) => { const error = new Error('服务器异常') error.errorCode = 10001 error.status = 500 error.requestUrl = `${ctx.method} ${ctx.path}` throw error }) app.use(catchError) app.use(router.routes()) .use(router.allowedMethods()) app.listen(3000) const catchError = async (ctx, next) => { try { await next() } catch(error) { if(error.errorCode) { ctx.body = { code: error.errorCode, msg: error.message, request: error.requestUrl } ctx.status = error.status } } } module.exports = catchError

    三.定义HttpException异常基类

    class HttpException extends Error { constructor(msg = '服务器异常', errorCode = 10000, status = 500) { super() this.msg = msg this.errorCode = errorCode this.status = status } } module.exports = HttpException const HttpException = require('./http-exception') const catchError = async (ctx, next) => { try { await next() } catch(error) { if(error instanceof HttpException) { ctx.body = { code: error.errorCode, msg: error.msg, request: `${ctx.method} ${ctx.path}` } ctx.status = error.status } } } module.exports = catchError const Koa = require('koa') const Router = require('koa-router') const catchError = require('./exception/exception') const HttpException = require('./exception/http-exception') const app = new Koa() const router = new Router() router.get('/api/v1/other/exception', async (ctx, next) => { const error = new HttpException() throw error }) app.use(catchError) app.use(router.routes()) .use(router.allowedMethods()) app.listen(3000)

    四.定义一系列特定异常类,继承自HttpException

    const HttpException = require('../exception/http-exception') class ParameterException extends HttpException { constructor(msg, errorCode) { super() this.msg = msg || '参数错误' this.errorCode = errorCode || 10001 this.status = 400 } } class NotFoundException extends HttpException { constructor(msg, errorCode) { super() this.msg = msg || '资源未找到' this.errorCode = errorCode || 10002 this.status = 404 } } module.exports = { ParameterException, NotFoundException } const requireDirectory = require('require-directory') const Router = require('koa-router') class InitManager { static initCore(app) { InitManager.app = app InitManager.initExceptions() InitManager.initRouters() } static initRouters() { let apiDirectory = `${process.cwd()}/app/api` requireDirectory(module, apiDirectory, {visit: function(obj) { if(obj instanceof Router) { InitManager.app.use(obj.routes()) .use(obj.allowedMethods()) } }}) } static initExceptions() { let errors = require('./api-exceptions') global.errors = errors } } module.exports = InitManager const Router = require('koa-router') const router = new Router() router.get('/api/v1/other/exception', async (ctx, next) => { const error = new global.errors.NotFoundException() throw error }) module.exports = router const Koa = require('koa') const catchError = require('./exception/exception') const InitManager = require('./core/init') const app = new Koa() app.use(catchError) InitManager.initCore(app) app.listen(3000)

    五.处理未知异常

    const HttpException = require('./http-exception') const catchError = async (ctx, next) => { try { await next() } catch(error) { if(error instanceof HttpException) { ctx.body = { code: error.errorCode, msg: error.msg, request: `${ctx.method} ${ctx.path}` } ctx.status = error.status } else { //未知错误 ctx.body = { code: 10000, msg: "服务器异常", request: `${ctx.method} ${ctx.path}` } } } } module.exports = catchError
    Processed: 0.015, SQL: 12