延迟保存要捕获创建时的实体

**延迟任务(debounce / setTimeout)在触发时才去读「当前活跃对象」,会在切换期间把 A 的数据写到 B 上。** 修法两条:创建任务时就捕获当时的实体 id 并显式传下去;实体短暂变为 `null` 时也要先 flush 待保存内容。

症状

「笔记无法编辑,始终显示同一份笔记」——切来切去内容互相覆盖,看起来像编辑器坏了。

根因链

  1. 正文编辑不是每敲一字就保存,而是 1 秒 debounce。
  2. 用户编辑 A 后 1 秒内切到 B。
  3. B 的完整正文还没加载完,父层传给编辑器的 note 短暂变成 null。
  4. 旧逻辑在 note === null 时直接 return,没有把 A 的待保存内容 flush 掉。
  5. 计时器随后触发,保存逻辑默认取「当前 active tab id」。
  6. 此时 active tab 已是 B → A 的正文被写进 B。

两层防护

  • note === null 时,也用 lastNoteIdRef 把上一条的 pending title/content 保存到旧 id;
  • debounce 创建时就捕获当前 note.id,触发时显式传这个 id,不再临时读当前 active tab。

可迁移的判断

「延迟执行 + 读取全局当前值」是一类通用 bug 形状,和业务无关:

  • 定时器 / debounce / 动画帧 / 请求重试,只要回调里读的是共享的可变当前指针,切换对象就会写错目标;
  • 修法统一是闭包捕获 + 显式传参,不要依赖回调执行时的环境状态;
  • 加载态(null / loading)不是「什么都不用做」,而是最需要 flush 的时刻。

相关