setTimeout() polyfill

(function() {
  let count = 1; // Can be generated.
  const timers = {}; // Can use priority queue based on time.

  const caller = () => {
    for (const [key, val] of Object.entries(timers)) {
      const {
        t,
        cb
      } = val;
      if (Date.now() >= t) {
        cb();
        myClearTimeout(key);
      }
    }
    requestIdleCallback(caller);
  };

  window.mySetTimeout = (cb, delay) => {
    timers[count] = {
      t: Date.now() + delay,
      cb
    };
    if (Object.keys(timers).length)
      requestIdleCallback(caller);
    return count++;
  }

  window.myClearTimeout = (id) => {
    if (id in timers) delete timers[id];
  }
})() // Immediately Invoked Function Expression (IIFE).

const id = mySetTimeout(() => {
  console.log('test')
}, 2000);
const id2 = mySetTimeout(() => {
  console.log('test2');
}, 1000);
myClearTimeout(id);

Demo