2

When using jest.useFakeTimers(), why do setTimeout() and setImmediate() behave differently?:

beforeAll(jest.useFakeTimers);
afterAll(jest.useRealTimers);

describe("timer behavior", () => {
  it('times out waiting for a setTimeout', async () => {
    await new Promise(setTimeout);
  });

  it('successfully resolves a setImmediate', async () => {
    await new Promise(setImmediate);
  });
});

The setTimeout() behavior makes sense to me, but why does a mocked setImmediate() resolve as usual?

1 Answers1

4

The difference between setImmediate and setTimeout is that set setImmediate schedules a callback for immediate execution "once the current poll phase completes" while setTimeout schedules a callback for execution "after a minimum threshold in ms has elapsed".

Even when the timeout is 0, setTimeout is still dependent on checking the passage of time, whereas setImmediate is not dependent on the clock in any way.

Because of this, callbacks scheduled with setTimeout will always wait until a simulated clock tick when using fake timers, whereas callbacks scheduled with setImmediate will execute right away.

If you look at the source code for Jest, the fake that it uses for setImmediate is just a thin wrapper that creates a cancellable callback and immediately calls the real setImmediate.

Brian Adams
  • 43,011
  • 9
  • 113
  • 111