This solution is generated by ChatGPT, correctness is not guaranteed.

AI solution for JavaScript Coding Question on BFE.dev
36. create a fake timer(setTimeout)

Solution:

class FakeTimer {
  constructor() {
    this.originalSetTimeout = null;
    this.originalClearTimeout = null;
    this.originalDateNow = null;

    this.queue = [];
    this.now = 0;
  }

  install() {
    this.originalSetTimeout = setTimeout;
    setTimeout = this.setTimeout.bind(this);

    this.originalClearTimeout = clearTimeout;
    clearTimeout = this.clearTimeout.bind(this);

    this.originalDateNow = Date.now;
    Date.now = this.nowFn.bind(this);
  }

  uninstall() {
    clearTimeout = this.originalClearTimeout;
    setTimeout = this.originalSetTimeout;
    Date.now = this.originalDateNow;
  }

  tick() {
    while (this.queue.length > 0) {
      const { callback, time } = this.queue.shift();

      this.now = time;
      callback();
    }
  }

  nowFn() {
    return this.now;
  }

  setTimeout(callback, delay) {
    const scheduledTime = this.now + delay;

    const timeoutId = { scheduledTime };
    this.queue.push({ callback: () => callback(), time: scheduledTime });

    this.queue.sort((a, b) => a.time - b.time);

    return timeoutId;
  }

  clearTimeout(timeoutId) {
    this.queue = this.queue.filter(({ time }) => time !== timeoutId.scheduledTime);
  }
}

// Testing

const fakeTimer = new FakeTimer();

let logs = [];
const log = (arg) => {
  logs.push([fakeTimer.now, arg]);
};

fakeTimer.install();

setTimeout(() => log('A'), 100);
setTimeout(() => log('C'), 500);
setTimeout(() => log('B'), 200);

fakeTimer.tick();

expect(logs).toEqual([[100, 'A'], [200, 'B']]);

logs = [];

fakeTimer.tick();

expect(logs).toEqual([[500, 'C']]);

logs = [];

const b = setTimeout(() => log('D'), 300);

fakeTimer.clearTimeout(b);

fakeTimer.tick();

expect(logs).toEqual([]);

fakeTimer.uninstall();

Explanation:

We create a class FakeTimer with setTimeout, clearTimeout, and Date.now methods, and an internal queue for scheduled callbacks.

In the install() method, we replace the original setTimeout, clearTimeout, and Date.now functions with our own implementations by binding them to this.

In our implementation of setTimeout, we create a scheduled time based on the current time (now) and the delay provided. We also store this scheduled time along with the callback function in our queue, which is sorted in ascending order by the scheduled time.

In our implementation of clearTimeout, we remove the scheduled callback from our queue by comparing the scheduled time with the provided timeoutId.

In our implementation of tick(), we execute all the scheduled callbacks for which the scheduled time is less than or equal to the current time (now). We also update the current time before executing the callback.

In our implementation of nowFn(), we simply return the current time (now).

In the testing code, we create a new instance of FakeTimer, and use it to schedule callbacks with setTimeout and clear scheduled callbacks with clearTimeout. We then call tick() to execute the scheduled callbacks, and compare the results with the expected output using the expect method. Finally, we call uninstall() to restore the original setTimeout, clearTimeout, and Date.now functions.