What would be a good approach to best implement setInterval using setTimeout?
Take into account that the mocked setInterval should be able to be "cleared".
What would be a good approach to best implement setInterval using setTimeout?
Take into account that the mocked setInterval should be able to be "cleared".
Here the intervalId is the reference object that contains the timeoutId. The reference object changes every time the setTimeout is called recursively.
const _setInterval = (callback, delay) => {
const timerRef = { id: null };
const timeout = () => {
timerRef.id = setTimeout(() => {
callback();
timeout();
}, delay);
}
timeout();
return timerRef;
};
const timerRef = _setInterval(() => {
console.log("Callback");
}, 1000);
setTimeout(() => {
clearTimeout(timerRef.id);
}, 5000);
To mock setInterval accurately, ons has to mock clearInterval too:
{
const intervals = new Map();
function setInterval(fn, time, context, ...args) {
const id = Math.floor(Math.random() * 10000);
intervals.set(id, setTimeout(function next() {
intervals.set(id, setTimeout(next, time));
fn.apply(context, args);
}, time));
return id;
}
function clearInterval(id) {
clearTimeout(intervals.get(id));
}
}
And you can use it as always:
const interval = setInterval(console.log, 100, console, "hi");
clearInterval(interval);
I have a promise based solution without recursion :)
function setInterval1(fn, time) {
let check = { check: true };
(async function () {
for (let i = 0; i < Number.POSITIVE_INFINITY && check.check; i++) {
await new Promise((resolve) => {
setTimeout(() => { fn(); resolve(true); }, time);
});
}
})();
return check;
}
let check = setInterval1(() => console.log('hi'), 1000);
function clearInterval1(check) {
check.check = false;
}
setTimeout(() => { clearInterval1(check) }, 4000)
setInterval using setTimeoutfunction interval(cb, ms){
var a = {
clear : function(){
clearTimeout(a.timer)
}
};
(function run(){
cb();
a.timer = setTimeout(run, ms);
})();
return a;
}
var myInterval_1 = interval(()=>{ console.log(1) }, 1000); // create an "interval"
var myInterval_2 = interval(()=>{ console.log(2) }, 1000); // create another "interval"
// clear the first interval
setTimeout(()=>{ myInterval_1.clear() }, 4000)
Another form to append it in window object and mimic global setInterval and clearInterval
(function (window) {
const idMap = {};
window.customSetInterval = (cb, duration) => {
let x = null;
const loop = (cb) => {
const y = setTimeout(() => {
cb();
loop(cb);
}, duration);
if (!idMap[x]) {
x = y;
}
idMap[x] = y;
};
loop(cb);
return x;
};
window.customClearInterval = (x) => {
clearTimeout(idMap[x]);
};
})(window);