Reputation: 130620
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".
Upvotes: 2
Views: 6749
Reputation: 190
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);
Upvotes: 0
Reputation: 89
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);
Upvotes: 5
Reputation: 2867
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)
Upvotes: 1
Reputation: 138537
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);
Upvotes: 4
Reputation: 130620
setInterval
using setTimeout
function 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)
Upvotes: 0