À medida que mais desenvolvedores de JavaScript escrevem se tornam assíncronos, é natural que seja necessário esperar que as condições sejam atendidas. Isso é especialmente verdadeiro em um mundo com testes assíncronos de condições que não fornecem uma função explícita de await. Já escrevi sobre waitForever, waitForTime, e Polling em JavaScript no passado, mas eu queria ter uma forma mais moderna de awaitde um determinado estado. Vamos dar uma olhada nesse super útil waitFor super útil!

waitFor é um async que permite que os desenvolvedores forneçam uma função de condição, um intervalo de sondagem (em milissegundos) e um tempo limite opcional (em milissegundos).

// Polls every 50 milliseconds for a given condition
const waitFor = async (condition, pollInterval = 50, timeoutAfter) => {
  // Track the start time for timeout purposes
  const startTime = Date.now();

  while (true) {
    // Check for timeout, bail if too much time passed
    if(typeof(timeoutAfter) === 'number' && Date.now() > startTime + timeoutAfter) {
      throw 'Condition not met before timeout';
    }

    // Check for conditon immediately
    const result = await condition();

    // If the condition is met...
    if(result) {
      // Return the result....
      return result;
    }

    // Otherwise wait and check after pollInterval
    await new Promise(r => setTimeout(r, pollInterval));
  }
};

Usar essa função é tão simples quanto fornecer uma função de condição:

await waitFor(() => document.body.classList.has('loaded'));

Também é simples cronometrar o intervalo e o tempo limite:

await waitFor(
  () => document.body.classList.has('loaded'),
  // Checks every 100 milliseconds
  100,
  // Throws if the "loaded" class isn't on the body after 1 second
  10000
);

Em um mundo ideal, os desenvolvedores sempre teriam um controle sobre o Promise que poderiam ser await‘d ou then‘d. Na prática, porém, isso nem sempre acontece, especialmente em um ambiente de teste. Ser capaz de aguardar uma condição em qualquer ambiente é uma necessidade absoluta, portanto, mantenha esse snippet em sua caixa de ferramentas!