requestanimationframe-timer
Version:
setTimeout and setInterval by using requestAnimationFrame
83 lines • 2.12 kB
JavaScript
import raf from 'raf';
var MODE;
(function (MODE) {
MODE[MODE["MODE_TIMEOUT"] = 0] = "MODE_TIMEOUT";
MODE[MODE["MODE_INTERVAL"] = 1] = "MODE_INTERVAL";
})(MODE || (MODE = {}));
const fnMap = new Map();
const executionSet = new Set();
let rafStarted = false;
let startId = 0;
function getTimeStamp() {
return new Date().getTime();
}
function executeFn(value) {
const { fn, args } = value;
fn(...args);
}
function runFunction() {
if (executionSet.size === 0)
return;
executionSet.forEach(executeFn);
executionSet.clear();
}
const checkTick = (currentTimeTick) => (value, id) => {
const { nextTick, ms, mode } = value;
if (currentTimeTick - nextTick >= 0) {
executionSet.add(value);
if (mode === MODE.MODE_TIMEOUT) {
fnMap.delete(id);
}
else {
fnMap.set(id, {
...value,
nextTick: nextTick + ms,
});
}
}
};
function loop() {
if (fnMap.size === 0) {
rafStarted = false;
return;
}
const currentTimeTick = getTimeStamp();
fnMap.forEach(checkTick(currentTimeTick));
runFunction();
if (fnMap.size === 0) {
rafStarted = false;
return;
}
raf(loop);
}
function addId({ fn, ms, args, mode }) {
if (!fn)
return null;
const currentId = startId;
fnMap.set(currentId, {
fn,
ms,
nextTick: getTimeStamp() + ms,
args,
mode,
});
if (!rafStarted) {
rafStarted = true;
raf(loop);
}
startId += 1;
return currentId;
}
function removeId(id) {
if (id == null)
return;
if (fnMap.has(id)) {
fnMap.delete(id);
}
}
export const setTimeout = (fn, ms = 0, ...args) => addId({ fn, ms, args, mode: MODE.MODE_TIMEOUT });
export const clearTimeout = removeId;
export const setInterval = (fn, ms = 0, ...args) => addId({ fn, ms, args, mode: MODE.MODE_INTERVAL });
export const clearInterval = removeId;
export default { setTimeout, clearTimeout, setInterval, clearInterval };
//# sourceMappingURL=index.js.map