如何在MongoDB持久化Y.js的yDoc并复用?解决doc.on()报错
解决TipTap协作扩展YDoc持久化到MongoDB后的
doc.on()不存在错误 错误核心原因
出现TypeError: doc.on() does not exist的本质是恢复后的YDoc实例异常,通常由以下两种情况导致:
- MongoDB存储/读取Uint8Array时的类型转换错误,导致
Y.applyUpdate无法正确解析状态,损坏YDoc实例。 - YDoc初始化方式或版本兼容性问题,导致创建的实例不符合TipTap协作扩展的要求。
具体解决方案
1. 修正MongoDB的二进制数据处理逻辑
MongoDB对Uint8Array的存储需要保持二进制类型,避免转成普通数组或字符串:
- 存储时:直接将
Y.encodeStateAsUpdate(yDoc)返回的Uint8Array存入,MongoDB会自动将其转为BinData(0)类型,无需额外处理:const update = Y.encodeStateAsUpdate(yDoc); await db.collection('docs').updateOne( { _id: docId }, { $set: { state: update } }, { upsert: true } ); - 读取时:将MongoDB返回的BinData转换回Uint8Array,不能直接使用原始返回值:
const storedDoc = await db.collection('docs').findOne({ _id: docId }); // 若使用Mongoose,需通过.buffer获取二进制数据 const updateUint8 = new Uint8Array(storedDoc.state.buffer);
2. 规范YDoc的初始化与状态恢复流程
- 优先使用TipTap提供的
createYDoc方法创建实例(确保与协作扩展兼容),而非直接new Y.Doc():import { createYDoc } from '@tiptap/core'; import * as Y from 'yjs'; const newDoc = createYDoc(); Y.applyUpdate(newDoc, updateUint8); - 若必须使用
new Y.Doc(),需确保yjs版本与@tiptap/extension-collaboration依赖的版本完全一致(版本不匹配会导致实例方法缺失)。
3. 适配Next.js 14客户端组件的执行时机
在客户端组件中,需将YDoc的恢复逻辑放在useEffect中执行,避免SSR hydration阶段的异常:
'use client'; import { useEffect, useState } from 'react'; import { EditorProvider } from '@tiptap/react'; import { Collaboration } from '@tiptap/extension-collaboration'; import { createYDoc } from '@tiptap/core'; import * as Y from 'yjs'; export default function Editor({ docId }) { const [yDoc, setYDoc] = useState(null); useEffect(() => { const restoreDoc = async () => { // 从API获取存储的状态 const res = await fetch(`/api/docs/${docId}`); const data = await res.json(); // 转换为Uint8Array const update = new Uint8Array(Object.values(data.state)); // 创建并恢复YDoc const doc = createYDoc(); Y.applyUpdate(doc, update); setYDoc(doc); }; restoreDoc(); }, [docId]); if (!yDoc) return <div>加载中...</div>; return ( <EditorProvider yDoc={yDoc} extensions={[Collaboration]}> {/* 编辑器内容 */} </EditorProvider> ); }
4. 验证版本兼容性
执行以下命令确保所有依赖版本匹配:
npm install yjs@latest @tiptap/core@latest @tiptap/extension-collaboration@latest
内容的提问来源于stack exchange,提问作者Raumil Dhandhukia
相关产品推荐
相关产品推荐

