svelte-realtime 0.1.5 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client.js +50 -6
- package/package.json +1 -1
package/client.js
CHANGED
|
@@ -4,6 +4,14 @@ import { writable } from 'svelte/store';
|
|
|
4
4
|
|
|
5
5
|
const _textEncoder = new TextEncoder();
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* RAF-based event batching for high-frequency streams (cursors, presence).
|
|
9
|
+
* In the browser, incoming pub/sub events are queued and flushed once per
|
|
10
|
+
* animation frame, reducing Svelte reactive updates from N-per-event to
|
|
11
|
+
* 1-per-frame. In Node/SSR, events apply synchronously (no DOM to protect).
|
|
12
|
+
*/
|
|
13
|
+
const _useRAF = typeof window !== 'undefined' && typeof requestAnimationFrame === 'function';
|
|
14
|
+
|
|
7
15
|
/**
|
|
8
16
|
* Typed error for RPC failures.
|
|
9
17
|
*/
|
|
@@ -535,18 +543,49 @@ function _createStream(path, options, dynamicArgs) {
|
|
|
535
543
|
return false;
|
|
536
544
|
}
|
|
537
545
|
|
|
546
|
+
/** @type {Array<{ event: string, data: any }>} Queued events waiting for next animation frame */
|
|
547
|
+
let _eventQueue = [];
|
|
548
|
+
|
|
549
|
+
/** @type {number | null} */
|
|
550
|
+
let _rafId = null;
|
|
551
|
+
|
|
538
552
|
/**
|
|
539
|
-
*
|
|
540
|
-
*
|
|
541
|
-
* @param {{ event: string, data: any }} envelope
|
|
553
|
+
* Flush all queued events in a single batch, then update the store once.
|
|
554
|
+
* Reduces reactive updates from N-per-event to 1-per-frame.
|
|
542
555
|
*/
|
|
543
|
-
function
|
|
544
|
-
|
|
545
|
-
if (
|
|
556
|
+
function _flushEvents() {
|
|
557
|
+
_rafId = null;
|
|
558
|
+
if (_eventQueue.length === 0) return;
|
|
559
|
+
const queue = _eventQueue;
|
|
560
|
+
_eventQueue = [];
|
|
561
|
+
for (let i = 0; i < queue.length; i++) {
|
|
562
|
+
_applyMerge(queue[i]);
|
|
563
|
+
}
|
|
564
|
+
if (Array.isArray(currentValue)) currentValue = currentValue.slice();
|
|
546
565
|
store.set(currentValue);
|
|
547
566
|
_recordHistory();
|
|
548
567
|
}
|
|
549
568
|
|
|
569
|
+
/**
|
|
570
|
+
* Apply a pub/sub event to the store. In the browser, events are queued
|
|
571
|
+
* and flushed once per animation frame to reduce reactive updates from
|
|
572
|
+
* N-per-event to 1-per-frame. In Node/SSR, events apply immediately.
|
|
573
|
+
* @param {{ event: string, data: any }} envelope
|
|
574
|
+
*/
|
|
575
|
+
function applyEvent(envelope) {
|
|
576
|
+
if (_useRAF) {
|
|
577
|
+
_eventQueue.push(envelope);
|
|
578
|
+
if (_rafId === null) {
|
|
579
|
+
_rafId = requestAnimationFrame(_flushEvents);
|
|
580
|
+
}
|
|
581
|
+
} else {
|
|
582
|
+
const replaced = _applyMerge(envelope);
|
|
583
|
+
if (!replaced && Array.isArray(currentValue)) currentValue = currentValue.slice();
|
|
584
|
+
store.set(currentValue);
|
|
585
|
+
_recordHistory();
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
550
589
|
/**
|
|
551
590
|
* Fetch initial data and subscribe to live updates.
|
|
552
591
|
*/
|
|
@@ -716,6 +755,11 @@ function _createStream(path, options, dynamicArgs) {
|
|
|
716
755
|
clearTimeout(_reconnectTimer);
|
|
717
756
|
_reconnectTimer = null;
|
|
718
757
|
}
|
|
758
|
+
if (_rafId !== null) {
|
|
759
|
+
cancelAnimationFrame(_rafId);
|
|
760
|
+
_rafId = null;
|
|
761
|
+
}
|
|
762
|
+
_eventQueue = [];
|
|
719
763
|
topic = null;
|
|
720
764
|
initialLoaded = false;
|
|
721
765
|
fetching = false;
|