Cómo posponer el trabajo hasta que finalice el desplazamiento

Funciones web: scrollend

El desplazamiento en la Web debe ser fluido y responsivo. Ejecutar tareas pesadas, como volver a calcular el diseño, hacer un seguimiento de las balizas de datos de estadísticas o actualizar el DOM de forma dinámica, durante el desplazamiento puede saturar el subproceso principal, lo que genera fotogramas perdidos y un diseño inestable.

Históricamente, los desarrolladores han dependido de la eliminación de rebotes del evento scroll con setTimeout() para adivinar cuándo finaliza un desplazamiento. Sin embargo, estas funciones de debounce son notoriamente poco confiables. Es posible que se activen mientras el usuario aún se desplaza.

El evento scrollend ofrece una solución muy confiable y orientada al rendimiento. El navegador activa un evento scrollend exactamente cuando se detiene un desplazamiento, finalizan todas las transiciones y se suelta un gesto táctil.

Cómo implementarla

Para implementar un patrón de aplazamiento de trabajo, haz lo siguiente:

  1. Configura un contenedor desplazable: Crea un contenedor con overflow: auto o overflow: scroll.
  2. Escucha eventos scroll: Usa este objeto de escucha solo para métricas dinámicas básicas o estilos de diseño informativos. No ejecutes tareas pesadas aquí.
  3. Detecta eventos scrollend: Registra una devolución de llamada scrollend en el contenedor de desplazamiento o en el documento.
  4. Ejecuta trabajo costoso en la devolución de llamada: Aquí es seguro recuperar contenido dinámico o activar diseños de DOM integrales.

Código de ejemplo

.scroll-container {
  height: 300px;
  overflow-y: auto;
}
const scroller = document.querySelector('.scroll-container');

// 1. Informative feedback during scroll
scroller.addEventListener('scroll', () => {
  // Avoid dynamic heavier data updates here
  console.log('Scrolling dynamically... updates deferred');
});

// 2. Safe callback when scrolling rests
scroller.addEventListener('scrollend', () => {
  // Run layout recalculations or analytical beacons updates here
  const currentVisibleSection = findMostVisibleSection(scroller);
  fetchAdditionalData(currentVisibleSection);
});

Implementación estratégica y prácticas recomendadas

  • SÍ uses scrollend en lugar de eventos scroll con rebote cuando actives balizas de datos de diseño o recuperes dinámicamente un nuevo diseño de contenido.
  • SÍ considera vincular esto con interacciones de ajuste scrollSnapChange o scrollSnapChanging si estás creando carruseles o diapositivas de galerías de testimonios.
  • NO agrupes las actualizaciones dinámicas que dependen del diseño dentro de las devoluciones de llamada de desplazamiento visual dinámico.
  • SÍ considera que el zoom y el desplazamiento del viewport visual activan el evento scrollend correctamente.

Estrategia de resguardo

En el caso de los navegadores no compatibles, recurre a un evento scroll con rebote con setTimeout para enviar un evento scrollend personalizado.

function initializeDemo() {
  const scroller = document.querySelector('#scroller');
  scroller.addEventListener('scrollend', () => {
    // Safe execution
  });
}

if ('onscrollend' in window) {
  initializeDemo();
} else {
  initializeDemo();
  const scroller = document.querySelector('#scroller');
  scroller.addEventListener('scroll', () => {
    clearTimeout(window.scrollendtimer);
    window.scrollendtimer = setTimeout(() => {
      scroller.dispatchEvent(new CustomEvent('scrollend'));
    }, 100);
  });
}