初版 Spec 中,我们约定了 Exception 的声明、抛出机制;
但捕获一节仅保留了临时的 onerror 实现,受制于 Koa 执行机制,并不完善,因此并未直接实现。
在上层框架开发实践中,我们发现,对于用户需要关注的异常大致有两类:
- 作用域在 Singleton 的异常
- 通常在生命周期中抛出
- 大多会被/有机会被显式
try-catch
- 剩余需要被框架主动处理(通常是:打点、打日志、通知 Daemon、退出进程)
- 作用域在 Execution 的异常
- 通常在业务代码中抛出
- 大多不适合被显式
try-catch(执行时机、代码冗余)
- 业务需要关心并主动进行处理(通常协议有关,如返回响应状态码、JSON 错误结构体)
- 一般与中间件有关
- 需要提供一套命名为
ExceptionFilter 的机制来用于在执行期处理
机制需要包括:
- 提供 Interface 用于编码实践,Filter 实体放入 IoC 容器
- 提供基于配置的注册机制,用于执行单元获取实体信息
- 在
Trigger 或 ExceptionHandler 中增加公共逻辑,用于统一执行 Filter
- 提供元信息语法糖用于处理指定错误码/错误实体的错误
需讨论的模糊问题:
- 不希望过度冲击已有的中间件序列(有用户习惯使用中间件处理错误,且经常不抛出),思路有二:
- 只在 Trigger 中增加特殊处理,在执行流最末尾执行 Filter
- 增加 ExceptionHandler.throw 处理逻辑,API 抛出后立即执行 Filter(是 ExceptionHandler 设计本意)
- 会冲击中间件序列中的 catch 逻辑
- 为了保证 throw xxx 仍然也能正常执行,Trigger 中的 catch 仍需存在
- 为了与中间件处理错误有所差异,不考虑引入 ctx,单个 Filter 不应关心其他 Filter,那就有可能出现多个 Filter 重复执行对协议响应的操作,有解法如下:
- Filter 全部依序执行,为单个 Filter 提供类似
done() 的 API,主动终止执行序列(API 不优雅)
- 规定通用的、针对单个错误码/实体的 Filter 唯一,不允许存在多个(通用性受限)
Spec 修改草案见 #27 中的 Markdown
初版 Spec 中,我们约定了 Exception 的声明、抛出机制;
但捕获一节仅保留了临时的 onerror 实现,受制于 Koa 执行机制,并不完善,因此并未直接实现。
在上层框架开发实践中,我们发现,对于用户需要关注的异常大致有两类:
try-catchtry-catch(执行时机、代码冗余)ExceptionFilter的机制来用于在执行期处理机制需要包括:
Trigger或ExceptionHandler中增加公共逻辑,用于统一执行 Filter需讨论的模糊问题:
done()的 API,主动终止执行序列(API 不优雅)Spec 修改草案见 #27 中的 Markdown