Fix batching of events

Instead of delaying edits to the Y.Doc, make all edits immediately. But
combine the resulting updates into a single update before sending it to
the other doc.
This commit is contained in:
2025-08-10 15:50:51 -07:00
parent 19a5a7bae6
commit 7b21812127
+25 -17
View File
@@ -19,7 +19,7 @@ const ta2 = document.getElementById('ta2') as HTMLTextAreaElement;
function bind(text: Y.Text, el: HTMLTextAreaElement) {
el.value = text.toString();
const handle = _.debounce(() => {
const handle = () => {
let prev = text.toString();
let curr = el.value;
let i = 0;
@@ -40,11 +40,32 @@ function bind(text: Y.Text, el: HTMLTextAreaElement) {
text.delete(offset, prev.length);
text.insert(offset, curr);
});
}, 500);
};
el.addEventListener('input', (_ev) => {
handle();
});
text.doc!.on('update', () => {
el.value = text.toString();
});
}
function pipe(src: Y.Doc, dest: Y.Doc) {
let prevStateVector = Y.encodeStateVector(src);
const flush = _.debounce(
() => {
const update = Y.encodeStateAsUpdate(src, prevStateVector);
prevStateVector = Y.encodeStateVector(src);
setTimeout(() => Y.applyUpdate(dest, update), _.random(2500, 5000));
},
1000,
{
maxWait: 2000,
}
);
src.on('update', flush);
}
const doc1 = new Y.Doc();
@@ -52,22 +73,9 @@ bind(doc1.getText(), ta1);
const doc2 = new Y.Doc();
bind(doc2.getText(), ta2);
doc1.on('update', async (update) => {
await new Promise((res, _rej) =>
setTimeout(res, 3000 * Math.random() + 2000)
);
Y.applyUpdate(doc2, update);
ta2.value = doc2.getText().toString();
});
doc2.on('update', async (update) => {
await new Promise((res, _rej) =>
setTimeout(res, 3000 * Math.random() + 2000)
);
Y.applyUpdate(doc1, update);
ta1.value = doc1.getText().toString();
});
pipe(doc1, doc2);
pipe(doc2, doc1);
doc1.getText().insert(0, 'foo bar baz');
ta1.value = doc1.getText().toString();
(window as any).Y = Y;