RxDB 异常机制
本文于1041天之前发表,文中内容可能已经过时。
RxDB 是一个由 JavaScript 实现,拥有响应式,离线优先等特性的数据库。它拥有以下特性:
- 多平台支持:浏览器、Node.js、Electron、Cordova、React-Native 和其它 JavaScript 运行时;
- 基于 RxJS 的响应式数据处理;
- 支持客户端与服务端之间的数据备份,兼容 PouchDB,CouchDB 和 IBM Cloudant;
- 基于易于学习的 jsonschema 标准;
- 提供 mongoDB 和 mongoose 类似的查询方式;
- 支持单个字段的加密,从而保护用户的隐私;
- 支持导入/导入 JSON 数据,非常适合 TDD;
- 支持不同浏览器窗口或 Node.js 进程之间数据同步;
- 支持 ORM。
接下来本文将基于 RxDB 的 7.5.1 版本,简单分析一下 RxDB 内部的异常机制。
基础知识
JavaScript 异常类型:
- EvalError —— 创建一个error实例,表示错误的原因:与
eval()
有关。 - InternalError —— 创建一个代表Javascript引擎内部错误的异常抛出的实例。 如: “递归太多”。
- RangeError —— 创建一个error实例,表示错误的原因:数值变量或参数超出其有效范围。
- ReferenceError —— 创建一个error实例,表示错误的原因:无效引用。
- SyntaxError —— 创建一个error实例,表示错误的原因:
eval()
在解析代码的过程中发生的语法错误。 - TypeError —— 创建一个error实例,表示错误的原因:变量或参数不属于有效类型。
- URIError —— 创建一个error实例,表示错误的原因:给
encodeURI()
或decodeURl()
传递的参数无效。
异常对象分类
在 RxDB 内部主要定义了两个异常类:
- RxError:继承于 Error 类
- RxTypeError:继承于 TypeError 类
利用 rx-error.js 文件提供的 newRxError 和 newRxTypeError 方法,我们可以方便地抛出自定义异常。在 encryption 插件内部,若数据库字段加密的密码的长度不为字符串或长度小于 8 时,则会抛出对应的异常。
具体的示例如下:
1 | export const overwritable = { |
newRxTypeError 函数
这里我们先来分析 RxError.newRxTypeError:
1 | export const newRxTypeError = (code, parameters) => |
其中 RxTypeError 继承于 TypeError,该类的实现如下:
1 | /* |
在 RxTypeError 构造函数内部,会调用 messageForError 函数,生成异常消息:
1 | const messageForError = (message, parameters) => { |
在 messageForError 函数内部,会进一步调用 parametersToString 函数进行参数对象
1 | /** |
JSON.stringify()
方法是将一个JavaScript值(对象或者数组)转换为一个 JSON 字符串,如果指定了 replacer 是一个函数,则可以替换值,或者如果指定了 replacer 是一个数组,可选的仅包括指定的属性。
关于序列化,有下面五点注意事项:
- 非数组对象的属性不能保证以特定的顺序出现在序列化后的字符串中。
- 布尔值、数字、字符串的包装对象在序列化过程中会自动转换成对应的原始值。
undefined
、任意的函数以及 symbol 值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成null
(出现在数组中时)。- 所有以 symbol 为属性键的属性都会被完全忽略掉,即便
replacer
参数中强制指定包含了它们。 - 不可枚举的属性会被忽略。
1 | JSON.stringify({}); // '{}' |
分析完 RxError.newRxTypeError,我们再来看一下 newRxError 函数。
newRxError 函数
1 | export const newRxError = (code, parameters) => |
RxError 类继承于 Error 类,具体实现如下:
1 | export class RxError extends Error { |
另外在创建异常消息时,内部会调用 overwritable.tunnelErrorMessage() 方法生成 code 对应的异常消息:
1 | /** |
不知道小伙伴有没有注意到 ‘EN1’ 和 ‘EN2’ 异常码,这些异常代码统一的定义在 error-message.js
文件的 CODES 对象中,该对象统一定义了 RxDB 中的所有异常信息:
1 | const CODES = { |
此外在 error-message 插件内部会重写默认的 tunnelErrorMessage 方法,从而正常的显示异常消息:
1 | export const overwritable = { |
最后再总结一下异常的处理流程:
- 调用 RxError 对象的 newRxTypeError() 方法,创建异常内置的异常对象。例如:
RxError.newRxTypeError('EN1', { password })
。 - 在 newRxTypeError 函数内部,会调用
overwritable.tunnelErrorMessage(code)
方法,根据异常代码,找出对应的异常信息(异常信息按照功能进行分类,定义在 error-message.js 文件内)。 - 之后调用
RxTypeError
构造函数,创建 RxTypeError 对象。在 RxTypeError 构造函数内部,会对传入的参数对象进行序列化处理,然后与 code 对应的错误信息进行拼接,最终生成完整异常信息。
总结
在 RxDB 内部主要定义了两个异常类:RxError 和 RxTypeError,并提供了 newRxTypeError 和 newRxError 两个函数,用于快速创建异常对象。
RxDB 异常处理机制,根据功能对异常代码进行分类,从而实现异常信息的统一管理。常见模块对应的异常代码映射关系如下:
- UT —— util.js
- P —— pouch-db.js
- QU —— rx-query.js
- MQ —— mquery.js
- DB —— rx-database
- COL —— rx-collection
- EN —— plugins/encryption.js
欢迎小伙伴们订阅全栈修仙之路,及时阅读 TypeScript、Node/Deno、Angular 技术栈最新文章。
