6

¿Cómo se reduce la frecuencia de las consultas de eventos de JavaScript? Los eventos que me preocupan son onResize y onScroll. Estos eventos pueden desencadenarse docenas de veces por segundo cuando alguien cambia el tamaño de su navegador o se desplaza hacia abajo, respectivamente. Me gustaría que estos eventos ocurrieran solo una vez cada 500 ms, así que no tengo que perder horas optimizando mis controladores de eventos y asegurándome de que no pierdan memoria.Disminuya la frecuencia de la encuesta de eventos de Javascript

Respuesta

9
var resizeTimeout; 

window.onresize = function() { 
    if (resizeTimeout) { 
     clearTimeout(resizeTimeout); 
    } 
    resizeTimeout = setTimeout(function() { 
     // Do it! 
    }, 500); 

}); 

Esto activará las funciones setTimeout() ~ 500 ms después de que hayan terminado de cambiar el tamaño.

La versión onscroll es muy similar :)

+3

este no se disparará cada 500 ms, solo se disparará 500 ms después de detener/detener el cambio de tamaño – Andrey

+0

+1 me gano. Recuerde incluir un cheque para 'resizeTimeout' ya que será' 'undefined' la primera vez. – casablanca

+0

@Andrey: Buen punto - Pasé por alto ese. – casablanca

5

Realmente no se puede controlar con qué frecuencia se activa el evento, se puede hacer algo como recordar el momento de la primera cocción de eventos, a continuación, en cada uno consiguiente comprobar si se trata de más de 500 ms desde el primero - si es así, proceda con el controlador de eventos; de lo contrario, simplemente salga del registro de eventos

+0

+1 para esta respuesta, entonces, esto es probablemente lo que quiere el OP. Sin embargo, necesita alguna lógica adicional para manejar el último evento de cambio de tamaño. – casablanca

+1

Creo que la solución del temporizador se ocupará del último evento de cambio de tamaño, por lo que la solución real sería una combinación de los dos – Andrey

1

Al comienzo de su controlador, verifique si han transcurrido 500ms desde el último, y solo regresar si no.

1

No puede evitar que se desencadenen estos eventos. Ellos siempre lo hacen. Lo que quiere hacer es dejar de escuchar de inmediato, luego manejar el evento para evitar la repetición. Luego, todo el controlador se configura nuevamente después de setTimeout. No ocurre más recursividad a menos que alguien cambie el tamaño de la ventana. Uso 5000ms aquí, ya que es más fácil verlo funcionar en la consola. No debería ver más de un correo no deseado en la consola de FF cada 5 segundos, incluso si cambia el tamaño como un spaz.

(function staggerListen(){ 
    window.onresize = function(){ 
    window.onresize = false; 
    console.log('spam'); 
    setTimeout(staggerListen,5000); 
    }; 
})() 

Utilizando la lógica para decidir si se debe hacer nada cada vez que los fuegos Handler es todavía técnicamente disparando un controlador y una sentencia if + búsqueda. Eso puede ser pesado.

+0

Wow. No estoy seguro de cuál es la sobrecarga para agregar/eliminar dinámicamente la devolución de llamada del oyente, pero +1 por ser complicado, de todos modos. :) – Phrogz

0

cheque el subrayado debounce función

crea y devuelve una nueva versión antirrebote de la función pasada que posponer su ejecución hasta después de esperar milisegundos que han transcurrido desde la última vez que fue invocada. Útil para implementar un comportamiento que solo debería ocurrir una vez que la entrada ha dejado de llegar. Por ejemplo: renderizar una vista previa de un comentario de reducción, volver a calcular un diseño después de que la ventana haya dejado de cambiar de tamaño, y así sucesivamente.

Ejemplo:

window.onscroll = _.debounce(
    function() { 
     // do something 
    }, 500, false 
); 
0

que utiliza para hacerlo como en la respuesta aceptada, pero el problema es que sólo se activa después de que el tiempo de espera especificado. Quería una solución que manejara el cambio de tamaño de inmediato, la primera vez. Esto es lo que terminé haciendo.

var _resize_is_busy = false; 
var _resize_scheduled = false; 
var _resize_precision = 100; 

// This register for window resize events. No need to change anything. 
$(window).resize(function() { 

    if (!_resize_is_busy) { 

     // call the scheduler who will do the work and set a timer to 
     // check of other resizes occured within a certain period of time 

     _resize_scheduler(); 
    } 
    else { 

     // the resizer is busy, i.e. a resize have been handled a little 
     // time ago and then the scheduler is waiting some time before 
     // handling any other resize. This flag tells the scheduler that 
     // a resize event have been receive while he was sleeping. 

     _resize_scheduled = true; 
    } 
}); 

// This is the scheduler. No need to change anything. 
var _resize_scheduler = function() { 

    _resize_is_busy = true; 
    _resize_scheduled = false; 

    setTimeout(function() { 

     _resize_is_busy = false; 

     if (_resize_scheduled) 
      _handle_resize(); 

    }, _resize_precision); 

    _handle_resize(); 
} 

var _handle_resize = function() { 

    console.log('DOING ACTUAL RESIZE'); 

    // do the work here 
    //... 
} 

Espero que esto ayude.

Cuestiones relacionadas