Cómo ceder el hilo principal para mejorar INP

Usa scheduler.yield() para dividir tareas largas y mantener tus páginas responsivas

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

Ceder el hilo principal

Imagina una película romántica. El escenario es un pequeño mercado francés en el centro de un pequeño pueblo. Las calles están llenas de parejas tomando café, comiendo croissants y comprando flores. Ahora imagina qué sucede cuando solo un comprador puede adquirir algo de un vendedor simultáneamente mientras todos los demás tienen que esperar su turno. El panadero se ve abrumado con pedidos, surgen discusiones en la floristería y el paseo romántico se convierte en una espera frustrante.

Bueno... eso es más o menos lo que sucede en un sitio web cuando las cosas se ponen demasiado ocupadas.

Última revisión por Arjen Karel en marzo de 2026

Por qué el yielding es importante para INP

El hilo principal de un navegador maneja todos los procesos importantes: analizar HTML y CSS, ejecutar JavaScript, manejar eventos de entrada como clics y desplazamientos, y el renderizado visual. Funciona con un modelo de un solo hilo, lo que significa que solo puede realizar una tarea a la vez. Cuando una tarea comienza a ejecutarse, el navegador la ejecutará hasta completarla y no se detendrá hasta que termine. Ninguna otra tarea se programa hasta que la actual finalice. Esto se llama bloquear el hilo principal.

Bloquear el hilo principal es la causa principal de puntuaciones pobres de Interaction to Next Paint (INP). Cuando un visitante hace clic en un botón y tu JavaScript bloquea el hilo principal durante 200ms, el navegador no puede pintar una respuesta hasta que el script termine. La fase de tiempo de procesamiento de INP mide exactamente este retraso. Según el Web Almanac 2025, el Total Blocking Time mediano en móvil es de 1.916ms, un aumento del 58% respecto al año anterior. Eso son casi 2 segundos en los que el navegador no puede responder a la entrada del usuario.

Una forma de solucionar esto es cediendo el hilo principal. El yielding es una técnica donde las tareas largas se dividen en múltiples tareas más pequeñas para permitir que el navegador maneje trabajo más importante (como responder a la entrada del usuario) entre ellas.

Tareas largas y período de bloqueo: Cuando una tarea tarda más de 50 milisegundos, se clasifica como tarea larga, y todo lo que supere ese umbral de 50 milisegundos se conoce como el "período de bloqueo" de la tarea. Dividir estas tareas largas en fragmentos más pequeños permite que el navegador permanezca responsivo, incluso al manejar operaciones computacionalmente intensivas.

Estrategias antiguas de yielding

Antes de la Prioritized Task Scheduling API había 4 formas de ceder el hilo principal. Todas tienen limitaciones.

  • setTimeout(): La estrategia más común. setTimeout() con un retraso de 0 añade la tarea al final de la cola, permitiendo que otras tareas se ejecuten primero. El problema: las tareas solo pueden enviarse al final de la cola, así que otros scripts pueden colarse antes de que tu código se reanude. Las llamadas anidadas a setTimeout() también imponen un retraso mínimo de 5ms después de cinco rondas.
  • requestAnimationFrame(): Pone en cola una función para ejecutarse antes del siguiente repintado del navegador. A menudo se combina con setTimeout() para asegurar que los callbacks se programen después de la siguiente actualización de layout. No está diseñado para yielding; está diseñado para trabajo de animación.
  • requestIdleCallback(): Más adecuado para tareas no críticas y de baja prioridad que pueden ejecutarse durante el tiempo de inactividad del navegador. La limitación: no hay garantía de que las tareas programadas se ejecuten con prontitud (o en absoluto) en un hilo principal ocupado.
  • isInputPending(): Verifica si hay entradas de usuario pendientes y cede solo si se detecta una entrada. Google ya no recomienda este enfoque. Puede devolver falsos negativos y no tiene en cuenta otro trabajo crítico para el rendimiento como animaciones y actualizaciones de renderizado.

scheduler.yield()

Las limitaciones de estos métodos han sido una preocupación para el equipo de Chrome, especialmente con muchos sitios que no pasan INP. Para abordar esto, construyeron scheduler.yield(): una nueva API que permite a los desarrolladores ceder el hilo principal inmediatamente sin reorganizar el orden de las tareas ni añadir complejidad.

scheduler.yield() se lanzó como estable en Chrome 129 (septiembre de 2024) y ahora es compatible con todos los navegadores principales excepto Safari.

Ejemplo de código

Como Safari aún no soporta scheduler.yield(), usa un fallback a setTimeout():

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

La función yieldToMain() verifica si window.scheduler.yield existe. Si es así, usa la API nativa. Si no, el código usa el fallback setTimeout(). Esto coincide con el patrón recomendado por Google.

Para proyectos que necesitan la Prioritized Task Scheduling API completa (incluyendo scheduler.postTask() y TaskController), Google Chrome Labs mantiene un polyfill oficial.

Ejemplo real: mejorando la búsqueda con yieldToMain()

Así es como yieldToMain() puede mejorar la experiencia de búsqueda para tus usuarios.

La función handleSearch() primero actualiza el contenido del botón para dar retroalimentación inmediata de que una búsqueda está en progreso, luego cede para permitir que el navegador pinte esa actualización. A continuación, fetchData() obtiene los datos de búsqueda y updateHTML(data) muestra los resultados. Otro yieldToMain() asegura una actualización rápida del layout. Finalmente, las tareas menos importantes se programan durante el tiempo de inactividad del navegador. Ten en cuenta que no cedí antes de requestIdleCallback() ya que solo se ejecuta cuando el hilo principal está inactivo de todos modos.

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 otro ejemplo práctico, consulta cómo usar este mismo patrón de yield con pushes al dataLayer para evitar que los scripts de analíticas bloqueen las interacciones.

Por qué scheduler.yield() es mejor

A diferencia de setTimeout(), que añade las tareas diferidas al final de la cola de tareas, scheduler.yield() pausa la ejecución y coloca la continuación al frente de la cola. Tu código se reanuda tan pronto como el trabajo de mayor prioridad (como manejar callbacks de entrada) se haya completado. Esta es la diferencia clave: puedes ceder el hilo principal sin el riesgo de que otros scripts se cuelen antes de que tu código se reanude.

scheduler.yield() también está diseñado para funcionar con la Prioritized Task Scheduling API. Cuando se llama dentro de un callback de scheduler.postTask(), scheduler.yield() hereda el nivel de prioridad de la tarea. Esta combinación te da un control detallado sobre cómo tu JavaScript se prioriza y cuándo cede.

Compatibilidad de navegadores

scheduler.yield() es compatible con el 71,5% de los navegadores a nivel global:

  • Chrome 129+ y Edge 129+: estable desde septiembre de 2024
  • Firefox 142+: estable desde agosto de 2025
  • Safari: no compatible, sin calendario anunciado

El fallback setTimeout() en la función yieldToMain() anterior asegura que tu código funcione en todos los navegadores. Los usuarios de Safari obtienen el comportamiento anterior donde las continuaciones van al final de la cola, pero la página aún cede. A medida que la compatibilidad de navegadores crezca, más usuarios obtendrán automáticamente la reanudación más rápida.

Si el problema son scripts de terceros bloqueando el hilo principal por completo, diferir esos scripts es un mejor primer paso que ceder. El yielding ayuda cuando tu propio código necesita hacer mucho trabajo pero quieres que el navegador permanezca responsivo entre fragmentos.

Para verificar que el yielding está mejorando tu INP en el campo, monitoriza tus páginas con Real User Monitoring. Las herramientas de laboratorio como Lighthouse miden el Total Blocking Time, pero solo los datos de campo te muestran el INP real que experimentan tus visitantes.

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.

17 years of fixing PageSpeed.

I have optimized platforms for some of the largest publishers and e-commerce sites in Europe. I provide the strategy, the code, and the RUM verification. Usually in 1 to 2 sprints.

View Services
Cómo ceder el hilo principal para mejorar INPCore Web Vitals Cómo ceder el hilo principal para mejorar INP