Loro 的事件处理
Loro 内置事件系统用于追踪文档变化。本节介绍事件的触发时机以及事务在 Loro 中的工作方式。
事件触发时机
只要内部文档状态发生变化,就会触发事件,帮助应用层的派生状态自动与文档同步。
-
本地操作:对于本地插入、删除等操作,Loro 会先将它们置于内部事务的 pending 状态。
-
事务提交:事务提交时,所有待处理操作会一次性触发相应事件。提交发生在以下场景:
- 显式调用
LoroDoc.commit() - 在导入或导出前自动提交
事件会在微任务结束后异步触发。如果需要在提交后立即处理事件,请等待一个微任务:
- 显式调用
const = new ();
.(() => {
.("Event:", );
});
const = .("text");
.(0, "Hello");
.();
// 事件尚未触发
await .();
// 事件现已触发- 导入:调用
import()导入远端更新时,会触发对应事件,便于本地响应其他节点的变更:
const = new ();
.(() => {
.("Event:", );
});
.(); // 微任务后触发事件
await .();- 版本切换:调用
doc.checkout(frontiers)切换到其他版本时,同样会在微任务后触发事件。
const = new ();
const = .();
.(); // 微任务后触发事件
await .();事务行为
Loro 的事务主要用于将相关操作打包,并以整体事件的形式发出,常见用途包括:
-
关联操作:当一系列本地操作在逻辑上相关时,你可能希望它们:
- 共享提交信息
- 使用相同时间戳
- 在撤销 / 重做时作为整体处理
-
事件处理:应用通常希望一次性收到相关变更,事务提供了:
- 在提交时设置 origin 标识
- 在事件中携带 origin 便于过滤
触发提交的方式
-
显式提交:直接调用
commit()。const = new (); const = .("myText"); .(0, "Hello, Loro!"); .(); // 提交待处理操作并触发事件 -
导入 / 导出前:在执行导入或导出前会自动提交。
const = new (); .(1); const = new (); .(2); // 对 doc1 与 doc2 进行一些操作 .("text").(0, "Alice"); .("text").(0, "Hello, Loro!"); .(.().()); // Map(0) {} .(.().()); // Map(0) {} const = .({ : "snapshot" }); .(); // doc2 会先提交自身待处理操作 .(.().()); // Map(2) { "1" => 5, "2" => 12 } .(.().()); // Map(2) { "1" => 5 }
Loro 中的事务
需要强调的是,Loro 的事务不同于传统数据库事务:
- 不具备 ACID 属性
- 主要充当事件包装器
- 操作失败时不会自动回滚