Skip to content

Instantly share code, notes, and snippets.

@leizongmin
Last active April 20, 2023 04:05
Show Gist options
  • Save leizongmin/92526235d89ee7dec11e52bd4ec26e01 to your computer and use it in GitHub Desktop.
Save leizongmin/92526235d89ee7dec11e52bd4ec26e01 to your computer and use it in GitHub Desktop.
Use `queueMicrotask` to implement timer function
function setTimeout(callback, delay, ...args) {
const id = setTimeout._nextId++;
const start = Date.now();
function loop() {
queueMicrotask(() => {
if (!setTimeout._timers[id]) return;
if (Date.now() - start >= delay) {
delete setTimeout._timers[id];
callback(...args);
} else {
loop();
}
});
}
setTimeout._timers[id] = [callback, ...args];
loop();
return id;
}
setTimeout._timers = {};
setTimeout._nextId = 1;
function clearTimeout(id) {
delete setTimeout._timers[id];
}
function setInterval(callback, interval, ...args) {
const id = setTimeout._nextId++;
let start = Date.now();
function loop() {
queueMicrotask(() => {
if (!setTimeout._timers[id]) return;
if (Date.now() - start >= interval) {
start = Date.now();
callback(...args);
loop();
} else {
loop();
}
});
}
setTimeout._timers[id] = [callback, ...args];
loop();
return id;
}
function clearTimeout(id) {
delete setTimeout._timers[id];
}
function clearInterval(id) {
clearTimeout(id);
}
console.log(Date.now());
const a = [111, 222, 333];
const b = [444, 555, 666];
let count = 0;
// timeout
setTimeout((...args) => console.log(Date.now(), ...args), 12345, ...a);
// interval
const id1 = setInterval(
(...args) => {
count++;
console.log(Date.now(), count, ...args);
if (count >= 5) {
clearInterval(id1);
}
},
1000,
...b
);
// cancel the timer
const id2 = setTimeout(() => console.log("timeout"), 1000);
clearTimeout(id2);
/*
will output something like:
1681963305259
1681963306260 1 444 555 666
1681963307260 2 444 555 666
1681963308260 3 444 555 666
1681963309260 4 444 555 666
1681963310260 5 444 555 666
1681963317605 111 222 333
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment