96 lines
2.9 KiB
JavaScript
96 lines
2.9 KiB
JavaScript
/* global ESDTimerWorker */
|
|
/*eslint no-unused-vars: "off"*/
|
|
/*eslint-env es6*/
|
|
|
|
let ESDTimerWorker = new Worker(URL.createObjectURL(
|
|
new Blob([timerFn.toString().replace(/^[^{]*{\s*/, '').replace(/\s*}[^}]*$/, '')], {type: 'text/javascript'})
|
|
));
|
|
ESDTimerWorker.timerId = 1;
|
|
ESDTimerWorker.timers = {};
|
|
const ESDDefaultTimeouts = {
|
|
timeout: 0,
|
|
interval: 10
|
|
};
|
|
|
|
Object.freeze(ESDDefaultTimeouts);
|
|
|
|
function _setTimer(callback, delay, type, params) {
|
|
const id = ESDTimerWorker.timerId++;
|
|
ESDTimerWorker.timers[id] = {callback, params};
|
|
ESDTimerWorker.onmessage = (e) => {
|
|
if (ESDTimerWorker.timers[e.data.id]) {
|
|
if (e.data.type === 'clearTimer') {
|
|
delete ESDTimerWorker.timers[e.data.id];
|
|
} else {
|
|
const cb = ESDTimerWorker.timers[e.data.id].callback;
|
|
if (cb && typeof cb === 'function') cb(...ESDTimerWorker.timers[e.data.id].params);
|
|
}
|
|
}
|
|
};
|
|
ESDTimerWorker.postMessage({type, id, delay});
|
|
return id;
|
|
}
|
|
|
|
function _setTimeoutESD(...args) {
|
|
let [callback, delay = 0, ...params] = [...args];
|
|
return _setTimer(callback, delay, 'setTimeout', params);
|
|
}
|
|
|
|
function _setIntervalESD(...args) {
|
|
let [callback, delay = 0, ...params] = [...args];
|
|
return _setTimer(callback, delay, 'setInterval', params);
|
|
}
|
|
|
|
function _clearTimeoutESD(id) {
|
|
ESDTimerWorker.postMessage({type: 'clearTimeout', id}); // ESDTimerWorker.postMessage({type: 'clearInterval', id}); = same thing
|
|
delete ESDTimerWorker.timers[id];
|
|
}
|
|
|
|
window.setTimeout = _setTimeoutESD;
|
|
window.setInterval = _setIntervalESD;
|
|
window.clearTimeout = _clearTimeoutESD; //timeout and interval share the same timer-pool
|
|
window.clearInterval = _clearTimeoutESD;
|
|
|
|
/** This is our worker-code
|
|
* It is executed in it's own (global) scope
|
|
* which is wrapped above @ `let ESDTimerWorker`
|
|
*/
|
|
|
|
function timerFn() {
|
|
/*eslint indent: ["error", 4, { "SwitchCase": 1 }]*/
|
|
|
|
let timers = {};
|
|
let debug = false;
|
|
let supportedCommands = ['setTimeout', 'setInterval', 'clearTimeout', 'clearInterval'];
|
|
|
|
function log(e) {
|
|
console.log('Worker-Info::Timers', timers);
|
|
}
|
|
|
|
function clearTimerAndRemove(id) {
|
|
if (timers[id]) {
|
|
if (debug) console.log('clearTimerAndRemove', id, timers[id], timers);
|
|
clearTimeout(timers[id]);
|
|
delete timers[id];
|
|
postMessage({type: 'clearTimer', id: id});
|
|
if (debug) log();
|
|
}
|
|
}
|
|
|
|
onmessage = function (e) {
|
|
// first see, if we have a timer with this id and remove it
|
|
// this automatically fulfils clearTimeout and clearInterval
|
|
supportedCommands.includes(e.data.type) && timers[e.data.id] && clearTimerAndRemove(e.data.id);
|
|
if (e.data.type === 'setTimeout') {
|
|
timers[e.data.id] = setTimeout(() => {
|
|
postMessage({id: e.data.id});
|
|
clearTimerAndRemove(e.data.id); //cleaning up
|
|
}, Math.max(e.data.delay || 0));
|
|
} else if (e.data.type === 'setInterval') {
|
|
timers[e.data.id] = setInterval(() => {
|
|
postMessage({id: e.data.id});
|
|
}, Math.max(e.data.delay || ESDDefaultTimeouts.interval));
|
|
}
|
|
};
|
|
}
|