Como fazer o yield para a thread principal e melhorar o INP

Use o scheduler.yield() para dividir tarefas longas e manter suas páginas responsivas

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-03-04

Yield para a thread principal

Imagine um filme romântico. O cenário é um pequeno mercado francês no centro de uma pequena vila. As ruas estão cheias de casais tomando café, comendo croissants e comprando flores. Agora imagine o que acontece quando apenas um comprador pode adquirir algo de um vendedor simultaneamente, enquanto todos os outros têm que esperar a sua vez. O padeiro fica sobrecarregado de pedidos, discussões começam na floricultura e o passeio romântico se transforma em uma espera frustrante.

Bem... é mais ou menos isso que acontece em um site quando as coisas ficam muito ocupadas.

Última revisão por Arjen Karel em março de 2026

Por que o yielding é importante para o INP

A thread principal de um navegador lida com todos os processos importantes: análise de HTML e CSS, execução de JavaScript, tratamento de eventos de entrada como cliques e rolagens, e renderização visual. Ela opera em um modelo de thread única, o que significa que só pode executar uma tarefa por vez. Quando uma tarefa começa a ser executada, o navegador a executará até a conclusão e não irá parar até que termine. Nenhuma outra tarefa é agendada até que a atual seja finalizada. Isso é chamado de bloqueio da thread principal.

Bloquear a thread principal é a principal causa de pontuações ruins de Interaction to Next Paint (INP). Quando um visitante clica em um botão e o seu JavaScript bloqueia a thread principal por 200ms, o navegador não consegue pintar uma resposta até que o script termine. A fase de tempo de processamento do INP mede exatamente esse atraso. De acordo com o Web Almanac de 2025, o Total Blocking Time mediano em dispositivos móveis é de 1.916ms, um aumento de 58% em relação ao ano anterior. São quase 2 segundos em que o navegador não consegue responder à entrada do usuário.

Uma maneira de corrigir isso é fazendo o yield para a thread principal. O yielding é uma técnica onde tarefas longas são divididas em múltiplas tarefas menores para permitir que o navegador lide com trabalhos mais importantes (como responder à entrada do usuário) entre elas.

Tarefas longas e período de bloqueio: Quando uma tarefa leva mais de 50 milissegundos, ela é classificada como uma tarefa longa, e qualquer coisa além desse limite de 50 milissegundos é conhecida como o "período de bloqueio" da tarefa. Dividir essas tarefas longas em pedaços menores permite que o navegador permaneça responsivo, mesmo ao lidar com operações computacionalmente intensivas.

Estratégias antigas de yielding

Antes da Prioritized Task Scheduling API, havia 4 maneiras de fazer o yield para a thread principal. Todas possuem limitações.

  • setTimeout(): A estratégia mais comum. O setTimeout() com um atraso de 0 adiciona a tarefa ao final da fila, permitindo que outras tarefas sejam executadas primeiro. O problema: as tarefas só podem ser empurradas para o final da fila, então outros scripts podem furar a fila antes que seu código seja retomado. Chamadas aninhadas de setTimeout() também impõem um atraso mínimo de 5ms após cinco rodadas.
  • requestAnimationFrame(): Coloca uma função na fila para ser executada antes da próxima repintura do navegador. Frequentemente combinada com setTimeout() para garantir que os callbacks sejam agendados após a próxima atualização de layout. Não foi projetada para o yielding; foi projetada para trabalhos de animação.
  • requestIdleCallback(): Mais adequada para tarefas não críticas e de baixa prioridade que podem ser executadas durante o tempo de inatividade do navegador. A limitação: não há garantia de que as tarefas agendadas serão executadas prontamente (ou sequer serão executadas) em uma thread principal ocupada.
  • isInputPending(): Verifica se há entradas de usuário pendentes e faz o yield apenas se uma entrada for detectada. O Google não recomenda mais esta abordagem. Pode retornar falsos negativos e não leva em conta outros trabalhos críticos para o desempenho, como animações e atualizações de renderização.

scheduler.yield()

As limitações desses métodos têm sido uma preocupação para a equipe do Chrome, especialmente com muitos sites falhando no INP. Para resolver isso, eles criaram o scheduler.yield(): uma nova API que permite aos desenvolvedores fazer o yield para a thread principal imediatamente, sem reorganizar a ordem das tarefas ou adicionar complexidade.

O scheduler.yield() foi lançado de forma estável no Chrome 129 (setembro de 2024) e agora é suportado por todos os principais navegadores, exceto o Safari.

Exemplo de código

Como o Safari ainda não suporta o scheduler.yield(), use um fallback para o setTimeout():

function yieldToMain() {
  if ('scheduler' in window && 'yield' in window.scheduler) {
    return window.scheduler.yield();
  }
  return new Promise((resolve) => {
    setTimeout(resolve, 0);
  });
}

A função yieldToMain() verifica se window.scheduler.yield existe. Se existir, ela usa a API nativa. Caso contrário, o código usa o fallback para setTimeout(). Isso corresponde ao padrão recomendado pelo Google.

Para projetos que precisam da Prioritized Task Scheduling API completa (incluindo scheduler.postTask() e TaskController), o Google Chrome Labs mantém um polyfill oficial.

Exemplo na vida real: aprimorando a pesquisa com yieldToMain()

Veja como o yieldToMain() pode melhorar a experiência de pesquisa para seus usuários.

A função handleSearch() primeiro atualiza o conteúdo do botão para dar um feedback imediato de que uma pesquisa está em andamento, e então faz o yield para permitir que o navegador pinte essa atualização. Em seguida, fetchData() recupera os dados da pesquisa e updateHTML(data) exibe os resultados. Outro yieldToMain() garante uma atualização rápida de layout. Por fim, tarefas menos importantes são agendadas durante o tempo de inatividade do navegador. Note que eu não fiz o yield antes de requestIdleCallback(), pois ele só é executado quando a thread principal já está ociosa de qualquer forma.

async function handleSearch() {
  /* quickly update the button content after submitting */
  updateButtonToPending();

  /* Yield to Main */
  await yieldToMain();

  /* fetch data and update html */
  const data = await fetchData();
  updateHTML(data);

  /* Yield to Main again */
  await yieldToMain();

  /* some functions should only run during browser idle time */
  requestIdleCallback(sendDataToAnalytics);
}

Para outro exemplo prático, veja como usar este mesmo padrão de yield com envios para a dataLayer para evitar que scripts de analytics bloqueiem interações.

Por que o scheduler.yield() é melhor

Ao contrário do setTimeout(), que adiciona tarefas adiadas ao final da fila de tarefas, o scheduler.yield() pausa a execução e coloca a continuação no início da fila. Seu código é retomado assim que um trabalho de maior prioridade (como o tratamento de callbacks de entrada) for concluído. Esta é a principal diferença: você pode fazer o yield para a thread principal sem o risco de outros scripts furarem a fila antes que seu código seja retomado.

O scheduler.yield() também foi projetado para funcionar com a Prioritized Task Scheduling API. Quando chamado dentro de um callback do scheduler.postTask(), o scheduler.yield() herda o nível de prioridade da tarefa. Essa combinação oferece um controle refinado sobre como seu JavaScript é priorizado e quando ele faz o yield.

Suporte de navegadores

O scheduler.yield() é suportado por 71,5% dos navegadores globalmente:

  • Chrome 129+ e Edge 129+: estáveis desde setembro de 2024
  • Firefox 142+: estável desde agosto de 2025
  • Safari: não suportado, sem cronograma anunciado

O fallback do setTimeout() na função yieldToMain() acima garante que seu código funcione em todos os navegadores. Os usuários do Safari obtêm o comportamento mais antigo, onde as continuações vão para o final da fila, mas a página ainda faz o yield. À medida que o suporte dos navegadores cresce, mais usuários obterão automaticamente a retomada mais rápida.

Se o problema for scripts de terceiros bloqueando a thread principal inteiramente, adiar (defer) esses scripts é um primeiro passo melhor do que fazer o yielding. O yielding ajuda quando o seu próprio código precisa fazer muito trabalho, mas você deseja que o navegador permaneça responsivo entre os trechos de código.

Para verificar se o yielding está melhorando o seu INP em campo, monitore suas páginas com o Real User Monitoring. Ferramentas de laboratório como o Lighthouse medem o Total Blocking Time, mas apenas dados de campo mostram o INP real que seus visitantes vivenciam.

About the author

Arjen Karel is a web performance consultant and the creator of CoreDash, a Real User Monitoring platform that tracks Core Web Vitals data across hundreds of sites. He also built the Core Web Vitals Visualizer Chrome extension. He has helped clients achieve passing Core Web Vitals scores on over 925,000 mobile URLs.

Escrevo código, não relatório.

Entro no seu time por 1 ou 2 sprints. Monto o monitoramento e garanto que o time mantém as métricas no verde depois que eu saio.

Entra em contato
Como fazer o yield para a thread principal e melhorar o INPCore Web Vitals Como fazer o yield para a thread principal e melhorar o INP