前言
Koa 是一款使用 Node.js 构建的 web 应用程序框架,比起 Express 更加轻盈灵活,适合搭建高性能的 web 应用。中间件是 Koa 的核心概念之一,理解中间件的执行流程及其捕获错误的原理对于开发高质量的 Koa 应用程序至关重要。
本文将简单介绍 Koa 中间件和错误捕获机制的基础知识,重点探讨如何处理 Koa 中间件 throw 异常,让你写出更加稳健的 web 应用程序。
Koa 中间件
Koa 中间件是请求处理流程中执行的函数,其通过调用 “next” 函数,将控制权交给下一个中间件。Koa 中间件可以是一个同步函数,如:
const Koa = require('koa'); const app = new Koa(); app.use((ctx, next) => { ctx.body = 'Hello World'; })
也可以是一个异步函数,如:
app.use(async (ctx, next) => { await next(); ctx.body += 'Goodbye!'; })
一旦有请求过来,Koa 就会自动执行路由对应的中间件。从上到下执行中间件,直到最后一个中间件返回响应,整个请求响应周期结束。
错误捕获
一旦一个中间件出现了异常,如读取不存在的文件,将一个空对象用作 awaitable,就有可能导致程序中止,从而返回用户一个 500 错误。为了更好地控制请求处理的错误流程,Koa 中引入了错误捕获机制,如果一个中间件捕获了异常,则 Koa 能自动切换到一个错误处理的中间件,用以处理这些异常。
一种比较好理解的错误捕获方式是使用 try catch。下面是一个演示代码:
-- -------------------- ---- ------- ------------- ----- ----- -- - --- - ----- ------ - ----- ----- - ---------- - -------------- -- ---------- -- ---- -------- - - -------- ----------- -- - --
在上面的代码中,我们使用 try catch 捕获了 next 异常并对其进行了处理,返回了一个带有错误信息的应答。之所以这种写法成立,是因为中间件之间互相包含,能保证异常按照正确的顺序传递给错误处理中间件。
Koa 中间件 throw 错误捕获
由于 Koa 对中间件的异常处理是基于 Promise 的,我们可以通过 throw 构造函数抛出异常,Koa 自动处理异常,这是为什么呢?我们可以看一下 Koa 内部是如何实现的。
Koa 在执行每一个中间件时都会调用 next() 函数,并且使用 Promise 将其包装,如下:
-- -------------------- ---- ------- --------- ------------ - ----- ------- - -------- ----- - ----- --- - ------------- ----- ------- - ----------- --------------- -- - ----------- --- -
Koa 借助 generator 函数和 Promise 实现了同步异步代码(异步通过coroutine转为Generator)统一。当中间件中 throw new error(errmsg); 时会中断,catch 错误并调用下一个中间件,如下:
-- -------------------- ---- ------- --------- ------------ - --- - ----- ------- - ----- ----- - -- ----- ----- - - -------- ----- - ----- --- - ------------- ----- ------- - ----------- --------------- -- - ----- ---------- ----- -------- - ------------- ----------------- --------- ----------------- -- - -- ----- ----- --- --- -
在 Koa 中处理异常,如果没有使用 try catch 捕获异常会抛出 Uncaught error 错误,导致应用程序宕机。如果使用 try catch 捕获,Koa 会将错误传递到错误处理中间件,如果没有指定错误处理中间件,则返回 500 错误。
-- -------------------- ---- ------- ------------- ----- ----- -- - ----- ------- -- ----------- --- ---- - -------- - ---- --- ------- - -- ------------- ----- ----- -- - ----- --- --------------- -------- --- --------------- ----- ---- -- - --------------------- ------- ----- -------- - ---- -------- ------ ------- ---
如果没有错误处理中间件,则会输出以下结果:
-- -------------------- ---- ------- --------------------------------- ------ -------- ----- -- ---------- ------------------------------------------ -- -------- -------------------------------------------------------------------- -- -------- -------------------------------------------------------------------- -- -------- -------------------------------------------------------------------- -- -------- -------------------------------------------------------------------- -- -------- -------------------------------------------------------------------- -- -------- -------------------------------------------------------------------- -- -------- -------------------------------------------------------------------- -- --------------- -------------------------------------------------------------------- ------------ --------------------------------- --------- ------- ---------- ---- ----- ---------- ------ -- -------- ------ -- -- ----- -------- ------- - ----- ------ -- -- --------- - ------- ----- --- --- ------- ---- --------- ---------- --- - ------------ --------- ------------------- --------- ------- ---------- --- ----------- -- --- ------- ------- ---------- ---- --- --- ------- ---- --------- --- ------- ------- ---- - -------- ---- ----- ------ ----- ------ -------- ----- -- ---------- ------------------------------------------ -- -------- -------------------------------------------------------------------- -- -------- -------------------------------------------------------------------- -- -------- -------------------------------------------------------------------- -- -------- -------------------------------------------------------------------- -- -------- -------------------------------------------------------------------- -- -------- -------------------------------------------------------------------- -- -------- -------------------------------------------------------------------- -- --------------- --------------------------------------------------------------------
Koa 在这种情况下会将返回错误代码绑定给上下文,因此我们可以将错误传递给自定义错误处理中间件中。
-- -------------------- ---- ------- ------------- ----- ----- -- - --- - ----- ------- - ----- ----- - ---------- - -------------- -- ---------- -- ---- -------- - - -------- ----------- -- - --- ------------- ----- ----- -- - ----- --- --------------- -------- --- ------------- ----- -- - -------- - ------ ------- --- ---------------- -- -- ------------------- ------- -- ---- --------
当发生未处理异常时,应答将是一个序列化的对象{'message': 'Intended Error'},状态码是500。
总结
中间件是 Koa 开发中最重要的概念之一,理解中间件的执行流程及其捕获错误的原理对于开发高质量的 Koa 应用程序至关重要。在 Koa 中如果使用 throw new error(errmsg) 来返回错误,Koa 会自动捕获异常并传递给错误处理中间件,我们只需要在应用程序中配置一个全局的错误处理中间件来统一处理错误即可。这种模式使用方便、效率高,在实战开发中使用十分广泛。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/648d1dc948841e9894b69ed5