- Em JavaScript,
setTimeout(0) na prática muitas vezes não executa imediatamente e acaba tendo um atraso mínimo de 4 ms, que é uma limitação padrão do navegador para evitar abusos
- Essas restrições existem para impedir que sites abusem indiscriminadamente de timers e causem consumo de bateria ou queda na interatividade; no modo de economia de bateria o limite pode subir para 16 ms, e em abas em segundo plano pode chegar a 1 segundo
- Para contornar as limitações do
setTimeout, desenvolvedores vêm usando várias APIs alternativas de timer, como setImmediate, MessageChannel.postMessage, window.postMessage e scheduler.postTask
- Em benchmarks reais, Chrome e Firefox aplicam o clamp de 4 ms, mas
MessageChannel e scheduler.postTask funcionam quase sem atraso, enquanto o Safari se destaca por restringir setTimeout de forma mais agressiva
- No fundo, trata-se de um equilíbrio entre proteger a experiência do usuário e preservar a liberdade dos desenvolvedores; hoje a Scheduler API vem se consolidando como solução padronizada, mas, se houver abuso, novos casos de intervenção do navegador (Intervention) ainda podem surgir
O contexto por trás das restrições do setTimeout
O surgimento de outras APIs de timer
setImmediate: suportado apenas no IE e no Edge antigo, hoje praticamente descontinuado
MessageChannel.postMessage: envia trabalho ao event loop por um canal separado
window.postMessage: tem bom desempenho, mas há risco de conflito com outros scripts
scheduler.postTask: suportado por navegadores modernos e considerado a opção mais estável
Resultados de benchmark (MacBook Pro 2021, 101 repetições)
- Chrome 139:
setTimeout 4.2ms, scheduler.postTask 0ms
- Firefox 142:
setTimeout 4.72ms, scheduler.postTask 0.01ms
- Safari 18.4:
setTimeout 26.73ms, MessageChannel 0.52ms, window.postMessage 0.05ms
Caso do fake-indexeddb
- O IndexedDB quer fazer commit automático da transação logo após o término das microtasks do event loop
- No Node.js,
setImmediate é ideal, mas no navegador setTimeout é ineficiente
- Um trabalho que leva 300 ms no Chrome chegou a se estender até 4,8 segundos no navegador
- Como solução, passou-se a usar
scheduler.postTask por padrão e, por compatibilidade, MessageChannel/window.postMessage como fallback
A controvérsia sobre intervenção do navegador
- Um lado argumenta que timers precisam ser limitados para que os desenvolvedores sejam protegidos de si mesmos
- O outro lado defende que é preciso garantir liberdade para que os desenvolvedores possam medir e otimizar por conta própria
- No fim, seguindo o princípio de priorizar o usuário, os navegadores intervêm para evitar abusos
- A Scheduler API tenta conciliar as duas posições, oferecendo controle fino de tarefas aos desenvolvedores enquanto se alinha ao pipeline de renderização do navegador
Perspectivas futuras
postTask e postMessage devem continuar sem throttling por enquanto
- Mas, se prioridades altas como
user-blocking forem usadas em excesso, novas intervenções podem voltar a acontecer
- No longo prazo, talvez seja necessário até mesmo outra API alternativa, como uma hipotética
scheduler2
Ainda não há comentários.