diff --git a/packages/rrweb/src/replay/machine.ts b/packages/rrweb/src/replay/machine.ts index 4409dd1151..fd4ad7bf68 100644 --- a/packages/rrweb/src/replay/machine.ts +++ b/packages/rrweb/src/replay/machine.ts @@ -188,7 +188,6 @@ export function createPlayerService( } const syncEvents = new Array(); - const actions = new Array(); for (const event of neededEvents) { if ( lastPlayedTimestamp && @@ -202,7 +201,7 @@ export function createPlayerService( syncEvents.push(event); } else { const castFn = getCastFn(event, false); - actions.push({ + timer.addAction({ doAction: () => { castFn(); }, @@ -212,7 +211,6 @@ export function createPlayerService( } applyEventsSynchronously(syncEvents); emitter.emit(ReplayerEvents.Flush); - timer.addActions(actions); timer.start(); }, pause(ctx) { diff --git a/packages/rrweb/src/replay/timer.ts b/packages/rrweb/src/replay/timer.ts index 6cfa95e0d6..89d66d4bc3 100644 --- a/packages/rrweb/src/replay/timer.ts +++ b/packages/rrweb/src/replay/timer.ts @@ -25,38 +25,40 @@ export class Timer { this.liveMode = config.liveMode; } /** - * Add an action after the timer starts. + * Add an action, possibly after the timer starts. */ public addAction(action: actionWithDelay) { + if ( + !this.actions.length || + this.actions[this.actions.length - 1].delay <= action.delay + ) { + // 'fast track' + this.actions.push(action); + return; + } + // binary search - events can arrive out of order in a realtime context const index = this.findActionIndex(action); this.actions.splice(index, 0, action); } - /** - * Add all actions before the timer starts - */ - public addActions(actions: actionWithDelay[]) { - this.actions = this.actions.concat(actions); - } public start() { this.timeOffset = 0; let lastTimestamp = performance.now(); - const { actions } = this; const check = () => { const time = performance.now(); this.timeOffset += (time - lastTimestamp) * this.speed; lastTimestamp = time; - while (actions.length) { - const action = actions[0]; + while (this.actions.length) { + const action = this.actions[0]; if (this.timeOffset >= action.delay) { - actions.shift(); + this.actions.shift(); action.doAction(); } else { break; } } - if (actions.length > 0 || this.liveMode) { + if (this.actions.length > 0 || this.liveMode) { this.raf = requestAnimationFrame(check); } };