Skip to content

Commit

Permalink
refactor due to performance optimization
Browse files Browse the repository at this point in the history
  • Loading branch information
Marcin Komorski authored and Marcin Komorski committed Jun 19, 2024
1 parent f93f84e commit ccf7b14
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 57 deletions.
63 changes: 22 additions & 41 deletions src/utils/focusTimeout.js
Original file line number Diff line number Diff line change
@@ -1,54 +1,35 @@
let activeFocusTimeouts = [];
let outOfFocusStart;
let timeOutOfFocus = 0;
let suspendedTimeouts = [];

document.addEventListener('visibilitychange', () => {
activeFocusTimeouts.forEach(({ pause, resume }) => document.hidden ? pause() : resume())
if (document.hidden) {
outOfFocusStart = Date.now()
} else {
timeOutOfFocus += Date.now() - outOfFocusStart
suspendedTimeouts.forEach(({ callback, startTime }) => setFocusTimeout(callback, timeOutOfFocus - startTime))
outOfFocusStart = null;
}
});

function removeFromActiveTimeouts(timerId) {
activeFocusTimeouts = activeFocusTimeouts.filter(timeout => timeout.timerId !== timerId);
}

export function clearFocusTimeout(timerId) {
clearTimeout(timerId);
removeFromActiveTimeouts(timerId);
}

/**
* Wraps native setTimeout function in order to count time only when page is focused
*
* @param {function(*): ()} [callback] - A function that will be invoked after passed time
* @param {number} [milliseconds] - Minimum duration (in milliseconds) that the callback will be executed after
* @returns {function(*): (number)} - Getter function for current timer id
* @returns {number} - timer id
*/
export default function setFocusTimeout(callback, milliseconds) {
let timerId;

timerId = setTimeout(() => {
removeFromActiveTimeouts(timerId);
callback();
const startTime = timeOutOfFocus;
const timerId = setTimeout(() => {
if (timeOutOfFocus === startTime && outOfFocusStart == null) {
callback();
} else if (outOfFocusStart != null) {
// case when timeout ended during page is out of focus
suspendedTimeouts.push({ callback, startTime })
} else {
setFocusTimeout(callback, timeOutOfFocus - startTime);
}
}, milliseconds);

let timeLeft = milliseconds;
let start = Date.now();

function pause() {
if (!timerId) return;
timeLeft -= Date.now() - start;
clearTimeout(timerId);
}

function resume() {
start = Date.now();
removeFromActiveTimeouts(timerId);
const getCurrentTimerId = setFocusTimeout(callback, timeLeft);
timerId = getCurrentTimerId();
}

activeFocusTimeouts.push({
timerId,
resume,
pause
})

return () => timerId;
return timerId;
}
7 changes: 3 additions & 4 deletions src/utils/ttlCollection.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {GreedyPromise} from './promise.js';
import {binarySearch, logError, timestamp} from '../utils.js';
import setFocusTimeout, { clearFocusTimeout } from './focusTimeout.js';
import setFocusTimeout from './focusTimeout.js';

/**
* Create a set-like collection that automatically forgets items after a certain time.
Expand Down Expand Up @@ -43,11 +43,11 @@ export function ttlCollection(
let nextPurge, task;

function reschedulePurge() {
task && clearFocusTimeout(task);
task && clearTimeout(task);
if (pendingPurge.length > 0) {
const now = timestamp();
nextPurge = Math.max(now, pendingPurge[0].expiry + slack);
const getTaskId = setFocusTimeout(() => {
task = setFocusTimeout(() => {
const now = timestamp();
let cnt = 0;
for (const entry of pendingPurge) {
Expand All @@ -66,7 +66,6 @@ export function ttlCollection(
task = null;
reschedulePurge();
}, nextPurge - now);
task = getTaskId();
} else {
task = null;
}
Expand Down
12 changes: 0 additions & 12 deletions test/spec/unit/utils/focusTimeout_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,4 @@ describe('focusTimeout', () => {
clock.tick(2000);
expect(callback.called).to.be.true;
});

it('should return updated timerId after page was showed again', () => {
let callback = sinon.stub();
const getCurrentTimerId = setFocusTimeout(callback, 4000);
const oldTimerId = getCurrentTimerId();
clock.tick(2000);
setDocumentHidden(true);
clock.tick(2000);
setDocumentHidden(false);
const newTimerId = getCurrentTimerId();
expect(oldTimerId).to.not.equal(newTimerId);
});
});

0 comments on commit ccf7b14

Please sign in to comment.