JavaScript高级技巧:构建零依赖实时数据同步系统
一、系统架构设计
数据变更 → 操作转换 → 状态同步 → 冲突解决 → 最终一致性
二、核心功能实现
1. 操作转换引擎
class OperationTransformer { constructor() { this.operations = []; } applyOperation(op) { // 转换新操作以考虑现有操作 const transformedOp = this.transformOperation(op); this.operations.push(transformedOp); return transformedOp; } transformOperation(newOp) { return this.operations.reduce((op, existingOp) => { if (op.type === 'insert' && existingOp.type === 'insert') { return this.transformII(op, existingOp); } if (op.type === 'delete' && existingOp.type === 'delete') { return this.transformDD(op, existingOp); } return this.transformID(op, existingOp); }, newOp); } transformII(newInsert, existingInsert) { // 处理两个插入操作的冲突 if (newInsert.position <= existingInsert.position) { return newInsert; } return { ...newInsert, position: newInsert.position + existingInsert.text.length }; } }
2. WebSocket同步层
class SyncClient { constructor(url) { this.ws = new WebSocket(url); this.queue = []; this.connected = false; this.ws.onopen = () => { this.connected = true; this.flushQueue(); }; this.ws.onmessage = (event) => { const message = JSON.parse(event.data); this.handleRemoteOperation(message); }; } sendOperation(op) { if (this.connected) { this.ws.send(JSON.stringify(op)); } else { this.queue.push(op); } } flushQueue() { while (this.queue.length > 0) { this.sendOperation(this.queue.shift()); } } handleRemoteOperation(remoteOp) { // 处理来自其他客户端的操作 document.dispatchEvent( new CustomEvent('remoteOperation', { detail: remoteOp }) ); } }
3. 客户端状态管理
class DocumentState { constructor() { this.text = ''; this.revision = 0; this.pendingOperations = []; } applyOperation(op) { switch (op.type) { case 'insert': this.text = this.text.slice(0, op.position) + op.text + this.text.slice(op.position); break; case 'delete': this.text = this.text.slice(0, op.position) + this.text.slice(op.position + op.length); break; } this.revision++; } addPendingOperation(op) { this.pendingOperations.push(op); } confirmOperation(op) { this.pendingOperations = this.pendingOperations.filter( pending => pending.id !== op.id ); } }
三、高级功能实现
1. 冲突解决策略
class ConflictResolver { static resolve(localState, remoteOp) { // 查找未确认的本地操作 const conflictingOps = localState.pendingOperations.filter( op => this.operationsOverlap(op, remoteOp) ); // 按操作时间戳排序 const sortedOps = [...conflictingOps, remoteOp].sort( (a, b) => a.timestamp - b.timestamp ); // 重新应用操作 let result = localState.text; sortedOps.forEach(op => { result = this.applySingleOperation(result, op); }); return result; } static operationsOverlap(op1, op2) { // 判断两个操作是否影响相同文本范围 } }
2. 离线同步支持
class OfflineManager { constructor() { this.pendingChanges = []; this.storageKey = 'unsyncedChanges'; this.loadChanges(); } addChange(change) { this.pendingChanges.push(change); this.saveChanges(); } getChanges() { return [...this.pendingChanges]; } clearChanges() { this.pendingChanges = []; localStorage.removeItem(this.storageKey); } loadChanges() { const saved = localStorage.getItem(this.storageKey); if (saved) { this.pendingChanges = JSON.parse(saved); } } saveChanges() { localStorage.setItem( this.storageKey, JSON.stringify(this.pendingChanges) ); } }
四、实战案例演示
1. 主应用集成
class CollaborativeEditor { constructor(textarea, wsUrl) { this.textarea = textarea; this.state = new DocumentState(); this.transformer = new OperationTransformer(); this.syncClient = new SyncClient(wsUrl); this.offlineManager = new OfflineManager(); this.setupEventListeners(); } setupEventListeners() { this.textarea.addEventListener('input', (e) => { const op = this.createOperationFromInput(e); this.state.applyOperation(op); this.transformer.applyOperation(op); this.syncClient.sendOperation(op); }); document.addEventListener('remoteOperation', (e) => { const resolved = ConflictResolver.resolve( this.state, e.detail ); this.textarea.value = resolved; this.state.text = resolved; }); } }
2. 性能优化方案
- 操作压缩:合并连续相同操作
- 增量同步:只发送差异部分
- 本地优先:优先响应本地操作
- 批量确认:减少网络请求