过期响应不能覆盖当前编辑内容
一、链路与故障点
CodeMirror(受控,value={note.content_md})
← React state(内存里的笔记对象)
← 后台 debounce 写 vault 文件
用户输入 A → 内存 A → 后台保存 A;继续输入 B → 内存 AB → 保存 AB。若「保存 A」比「保存 AB」更晚返回,旧代码把 {...n, ...patch, updated_at: now} 合并回内存,patch 里带着旧 content_md,CodeMirror 收到 value=A,画面回退。
二、为什么保存返回本来就要回写内存
保存成功带回的是只有后端才知道的结果:updated_at(列表排序/时间显示)、title 变化导致的 slug / 文件名变化(untitled.md → 项目复盘.md)、content_loaded 状态。所以不能「保存返回就一律不回写」。
正确边界:
| 内容 | 能否回写 |
|---|---|
updated_at / slug / id / content_loaded | ✅ 回写 |
content_md | 仅当没有更晚的本地输入时才允许 |
一句话:保存成功可以更新元信息,但不能用过期正文覆盖正在编辑的正文。
三、同源的显示问题:live preview 由光标位置决定
Markdown live preview 里 --- 与横线同时出现,是因为规则写成了「光标在本行:显示 ---,但仍然画横线」。改成光标在本行只显示源码 ---,离开本行才隐藏源码、只显示渲染结果,才是 Obsidian 那种体验。
两者共享同一主题:编辑器显示什么,要由「本地最新状态 / 光标位置」决定,而不是由过期的远端返回或固定的渲染规则决定。
相关
- 延迟保存要捕获创建时的实体 —— 同一保存链路的另一种乱序:写错目标对象
- 编辑即时反馈与落盘延迟分离 —— 延迟多久、延迟什么
- 流式更新要合并字段而非替换对象 —— 另一类「静默覆盖」的更新 bug