Skip to content

错误的分类与处置 ​

Makoo 不按「出了什么问题」给错误分类,而是按在哪里出现、由谁处理来分类。知道一个错误属于哪一类,就知道该去哪里找它、它会不会影响功能运行。

完整错误码见 错误 API。

五类错误 ​

类别何时出现你在哪里看到对功能的影响
配置错误useAdapter()、apply() 时同步抛出整批都不启动
控制错误调用命令或查询入口时同步抛出这次调用无效
执行失败运行过程中lastError、控制台结束这一轮,状态 failed
清理失败收尾过程中lastError、控制台、stop() / remove() 的拒绝注入被关闭
回调异常你的回调抛错时控制台,部分写入 lastError不影响

配置错误:开始前就报告 ​

名称重复、附属监听设置了 reinject、组件选择的适配器未注册、传给 apply() 的数组为空,或其中某一项不是组件、Each 注入或监听声明,都会在 apply() 时同步抛出,并且整批声明都不会启动。重复注册同名适配器则会在 useAdapter() 时同步抛出。完整列表见配置错误码。

这样做是为了避免一批功能启动到一半才发现另一半配置有误,留下难以解释的部分状态。配置错误通常在开发阶段第一次打开页面时就会出现,直接修改代码即可。

控制错误:这次调用不被允许 ​

对不存在的名称调用 core.injection() 或 core.listener(),启动已经移除的注入,在 Makoo 挂载的组件之外调用 useMakooComponent(),都属于控制错误。它们同步抛出,说明调用方的假设与当前状态不符。

执行失败:这一轮结束,可以再来 ​

执行失败发生在启动之后,例如等不到目标、适配器挂载抛错、目标失效且不允许恢复。因为它发生在后台,apply() 早已返回,所以 Core 不会抛出,而是:

  • 把错误写入状态入口的 lastError;
  • 用 console.error 打印错误对象;
  • 收尾成功后把状态设为 failed。

执行失败不会自动重试,但收尾成功后可以再次 start()。例如目标是用户操作后才出现的,可以在合适的时机手动启动。如果收尾本身也失败(例如适配器挂载失败后无法释放干净),就按下面的清理失败处理。

清理失败:无法确认干净,就不再继续 ​

收尾时,卸载组件、移除容器或解绑事件失败,Core 就无法确认页面上没有残留。此时注入被关闭:状态为 failed,lastError 是汇总所有错误的 MakooAggregateError,名称继续占用,之后的 start() 抛出 MAKOO_INJECTION_CLOSED。

如果清理是由 stop() 或 remove() 触发的,它们返回的 Promise 也会以同一个错误对象拒绝。dispose() 则以 MAKOO_INSTANCE_CLEANUP_FAILED 拒绝,各注入的清理错误在它的 errors 中。原因见为什么清理失败会关闭注入。

回调异常:只报告,不扩大 ​

Core 会调用不属于它的代码:事件处理函数、状态订阅者、observe() 回调。这些代码同步抛错时,Core 只报告,不把它当成执行失败:事件绑定保持,组件不卸载,状态不变,其他订阅者照常收到通知。

理由是这类错误通常只影响这一次处理。如果因为一次点击的处理函数出错就卸载组件、解绑全部事件,局部问题就会变成整个功能不可用。

报告方式略有不同:

来源控制台lastError实例观察
独立监听的事件处理函数打印写入不通知
附属监听的事件处理函数打印不写入不通知
状态订阅者打印不写入diagnostic
observe() 回调打印不适用diagnostic(不带 name)

事件处理函数返回被拒绝的 Promise 时也按上表报告。状态订阅者和 observe() 回调返回的 Promise 不会被等待,其中的拒绝 Makoo 不会接住。

状态订阅者的异常不写入 lastError,是因为订阅者往往在状态变为 failed 时被调用;如果写入,就会覆盖真正的失败原因。

读懂一个错误 ​

Makoo 抛出或报告的错误都是 MakooError,关键字段有三个:

  • message:Makoo 在做什么、对象是谁,例如 Failed to mount "panel"。
  • code:错误种类,在代码中用 MakooErrorCode 常量比较。
  • cause:Makoo 接住的原始错误,例如你的组件在 setup 中抛出的错误。

Makoo 只在接住别人的错误时包装一层,超时、目标失效这类自己判定的问题直接报告、不带 cause。在浏览器控制台展开错误,沿 cause 往下就能找到原始代码行。汇总错误(MakooAggregateError)另有 errors,列出每一个子错误,不会丢失;其中适配器给出的清理错误会原样保留,不一定是 MakooError。

Makoo 没有自己的日志系统,控制台是唯一的输出位置。需要在代码中处理错误时,读取状态入口的 lastError,或在状态变为 failed 时做出反应,见常见问题。