Tracker events throttling (#3399)
* add throttling * fix throttling * fix throttling
This commit is contained in:
parent
0139e0f1d5
commit
0d3a2015b2
2 changed files with 54 additions and 3 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
import { createMutationObserver } from '../../utils.js'
|
import { createMutationObserver, throttleWithTrailing } from '../../utils.js'
|
||||||
import {
|
import {
|
||||||
RemoveNodeAttribute,
|
RemoveNodeAttribute,
|
||||||
SetNodeAttributeURLBased,
|
SetNodeAttributeURLBased,
|
||||||
|
|
@ -413,6 +413,11 @@ export default abstract class Observer {
|
||||||
this.app.attributeSender.sendSetAttribute(id, name, value)
|
this.app.attributeSender.sendSetAttribute(id, name, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private throttledSetNodeData = throttleWithTrailing<number, [Element, string]>(
|
||||||
|
(id, parentElement, data) => this.sendNodeData(id, parentElement, data),
|
||||||
|
30
|
||||||
|
);
|
||||||
|
|
||||||
private sendNodeData(id: number, parentElement: Element, data: string): void {
|
private sendNodeData(id: number, parentElement: Element, data: string): void {
|
||||||
if (hasTag(parentElement, 'style')) {
|
if (hasTag(parentElement, 'style')) {
|
||||||
this.app.send(SetCSSDataURLBased(id, data, this.app.getBaseHref()))
|
this.app.send(SetCSSDataURLBased(id, data, this.app.getBaseHref()))
|
||||||
|
|
@ -570,7 +575,7 @@ export default abstract class Observer {
|
||||||
} else if (isTextNode(node)) {
|
} else if (isTextNode(node)) {
|
||||||
// for text node id != 0, hence parentID !== undefined and parent is Element
|
// for text node id != 0, hence parentID !== undefined and parent is Element
|
||||||
this.app.send(CreateTextNode(id, parentID as number, index))
|
this.app.send(CreateTextNode(id, parentID as number, index))
|
||||||
this.sendNodeData(id, parent as Element, node.data)
|
this.throttledSetNodeData(id, parent as Element, node.data)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -591,7 +596,7 @@ export default abstract class Observer {
|
||||||
throw 'commitNode: node is not a text'
|
throw 'commitNode: node is not a text'
|
||||||
}
|
}
|
||||||
// for text node id != 0, hence parent is Element
|
// for text node id != 0, hence parent is Element
|
||||||
this.sendNodeData(id, parent as Element, node.data)
|
this.throttledSetNodeData(id, parent as Element, node.data)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -640,5 +645,6 @@ export default abstract class Observer {
|
||||||
disconnect(): void {
|
disconnect(): void {
|
||||||
this.observer.disconnect()
|
this.observer.disconnect()
|
||||||
this.clear()
|
this.clear()
|
||||||
|
this.throttledSetNodeData.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -320,3 +320,48 @@ export function simpleMerge<T>(defaultObj: T, givenObj: Partial<T>): T {
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function throttleWithTrailing<K, Args extends any[]>(
|
||||||
|
fn: (key: K, ...args: Args) => void,
|
||||||
|
interval: number
|
||||||
|
): ((key: K, ...args: Args) => void) & { clear: () => void } {
|
||||||
|
const lastCalls = new Map<K, number>();
|
||||||
|
const timeouts = new Map<K, ReturnType<typeof setTimeout>>();
|
||||||
|
const lastArgs = new Map<K, Args>();
|
||||||
|
|
||||||
|
const throttled = function (key: K, ...args: Args) {
|
||||||
|
const now = Date.now();
|
||||||
|
const lastCall = lastCalls.get(key) ?? 0;
|
||||||
|
const remaining = interval - (now - lastCall);
|
||||||
|
|
||||||
|
lastArgs.set(key, args);
|
||||||
|
|
||||||
|
if (remaining <= 0) {
|
||||||
|
if (timeouts.has(key)) {
|
||||||
|
clearTimeout(timeouts.get(key)!);
|
||||||
|
timeouts.delete(key);
|
||||||
|
}
|
||||||
|
lastCalls.set(key, now);
|
||||||
|
fn(key, ...args);
|
||||||
|
} else if (!timeouts.has(key)) {
|
||||||
|
const timeoutId = setTimeout(() => {
|
||||||
|
lastCalls.set(key, Date.now());
|
||||||
|
timeouts.delete(key);
|
||||||
|
const finalArgs = lastArgs.get(key)!;
|
||||||
|
fn(key, ...finalArgs);
|
||||||
|
}, remaining);
|
||||||
|
timeouts.set(key, timeoutId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
throttled.clear = () => {
|
||||||
|
for (const timeout of timeouts.values()) {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
}
|
||||||
|
timeouts.clear();
|
||||||
|
lastArgs.clear();
|
||||||
|
lastCalls.clear();
|
||||||
|
};
|
||||||
|
|
||||||
|
return throttled;
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue