Sobes.tech
Middle

Why do we store timeoutId? What will happen if the Promise resolves before the timeout, and then the setTimeout with reject is triggered?

sobes.tech AI

Answer from AI

We store timeoutId to be able to cancel a delayed function execution, for example, a call to reject via setTimeout. If the Promise resolves before the timeout (for example, resolve is called), and then a setTimeout with reject fires, without canceling the timeout, reject will still be called, which can lead to undesired state changes or errors.

Therefore, after the Promise successfully resolves or rejects, you should call clearTimeout(timeoutId) to prevent the subsequent reject from the timeout.

Example:

function withTimeout(promise, ms) {
  let timeoutId;
  const timeoutPromise = new Promise((_, reject) => {
    timeoutId = setTimeout(() => reject(new Error('Timeout')), ms);
  });

  return Promise.race([
    promise.finally(() => clearTimeout(timeoutId)),
    timeoutPromise
  ]);
}

Without storing and clearing timeoutId, a situation can occur where the Promise has already settled, but the timeout still triggers reject, which would violate the logic.