javascript - pagina - onload jquery




Scroll evento disparando demasiadas veces. Solo quiero disparar un máximo de, digamos, una vez por segundo (6)

Aquí hay una solución que no requiere el uso de una biblioteca o un complemento JS adicional, que apunta a la simplicidad. Puede que no sea tan eficiente como otras implementaciones, pero definitivamente es un paso adelante de disparar tu evento principal cada vez que te desplazas.

Esto fue tomado de esta publicación del blog por Danny Van Kooten. Que he usado para retrasar mis eventos onscroll() para mi botón de volver a subir a mi blog.

var timer;
$(window).scroll(function() {
    if(timer) {
        window.clearTimeout(timer);
    }
    timer = window.setTimeout(function() {
       // actual code here. Your call back function.
    console.log( "Firing!" );
    }, 100);
});

También puede mejorar aún más el rendimiento al sacar variables de la función de devolución de llamada para evitar recálculos innecesarios, por ejemplo, el valor de $(window).height() o la altura de algún elemento div estático que no cambiará una vez que se cargue la página .

Aquí hay un ejemplo que está adaptado de mi caso de uso.

var scrollHeight = $("#main-element").height(); //never changes, no need to recalculate.
$(window).on('scroll', function() {
    if (timer) 
        window.clearTimeout(timer);
    timer = window.setTimeout(function() {
        var scrollPosition = $(window).height() + $(window).scrollTop();    
        if ($(window).scrollTop() < 500)
            $(".toggle").fadeIn(800);
        else 
            $(".toggle").fadeOut(800);
    }, 150); //only fire every 150 ms.
});

Esto limita la función real para que solo se ejecute cada 150 ms, o si no restablece el temporizador a 0 si 150ms no han pasado. Ajusta el valor para que se ajuste a lo que necesitas.

Tengo una página con "desplazamiento infinito". Calcula la diferencia entre el final de la página y la página actual y carga más contenido si esta diferencia es lo suficientemente pequeña. El código es parecido a esto usando jQuery:

$(window).on('scroll', function() {
    if (window.pageYOffset > loadMoreButton.offsetTop - 1000)
        # load more content via ajax
}

Ahora, el problema es que cada vez que me desplazo, este evento dispara varias veces por desplazamiento. Me gustaría disparar a lo sumo cada x milisegundos. ¿Cómo haría esto?


Consulte el método "acelerador" de la biblioteca Underscore.js.

http://underscorejs.org/#throttle

El ejemplo que proporciona es exactamente lo que está preguntando, lo que limita la frecuencia con la que debe manejar los eventos de desplazamiento.


No necesita un gran segmento de código para una función de aceleración decente. El propósito de una función del acelerador es reducir los recursos del navegador, no aplicar tanta sobrecarga que está utilizando aún más. Además, mis diferentes usos para las funciones del acelerador requieren muchas circunstancias diferentes para ellos. Aquí está mi lista de cosas que una 'buena' función de acelerador necesita que esta tenga.

  • Mínimo sobrecarga
  • Llamada de función inmediata si ha sido más que intervalo MS desde la última llamada.
  • Evitar la ejecución de la función para otro intervalo MS.
  • Retrasando la activación excesiva de eventos en lugar de descartar el evento por completo.
  • Actualiza el evento retrasado cuando sea necesario para que no se convierta en "obsoleto".
  • Impide la acción predeterminada del evento cuando la función de aceleración se retrasa.
  • Ser capaz de eliminar el oyente de escucha de eventos de aceleración.

Y, creo que la siguiente función del acelerador satisface todos esos.

var cachedThrottleFuncs = [],
    minimumInterval = 200; // minimum interval between throttled function calls
function throttle(func, obj, evt) {
    var timeouttype = 0,
        curFunc;
    function lowerTimeoutType(f){
        timeouttype=0;
        if (curFunc !== undefined){
            curFunc();
            curFunc = undefined;
        }
    };
    return cachedThrottleFuncs[ ~(
        ~cachedThrottleFuncs.indexOf(func) || 
        ~(
          cachedThrottleFuncs.push(function(Evt) {
            switch (timeouttype){
                case 0: // Execute immediatly
                    ++timeouttype;
                    func.call(Evt.target, Evt);
                    setTimeout(lowerTimeoutType, minimumInterval);
                    break;
                case 1: // Delayed execute
                    curFunc = func.bind(Evt.target, Evt);
                    Evt.preventDefault();
            }
          }) - 1
        )
    )];
};
function listen(obj, evt, func){
    obj.addEventListener(evt, throttle(func, obj, evt));
};
function mute(obj, evt, func){
    obj.removeEventListener(evt, throttle(func, obj, evt));
}

Ejemplo de uso:

listen(document.body, 'scroll', function whenbodyscrolls(){
    if (document.body.scrollTop > 400)
        mute(document.body, 'scroll', whenbodyscrolls();
    else
        console.log('Body scrolled!')
});

Alternativamente, si solo necesita agregar detectores de eventos y no necesita eliminar los detectores de eventos, puede usar la siguiente versión aún más simple.

var minimumInterval = 200; // minimum interval between throttled function calls
function throttle(func, obj, evt) {
    var timeouttype = 0,
        curEvt = null;
    function lowerTimeoutType(f){
        timeouttype=0;
        if (curEvt !== null){
            func(curEvt);
            curEvt = null;
        }
    };
    return function(Evt) {
        switch (timeouttype){
            case 0: // Execute immediately
                ++timeouttype; // increase the timeouttype
                func(Evt);
                // Now, make it so that the timeouttype resets later
                setTimeout(lowerTimeoutType, minimumInterval);
                break;
            case 1: // Delayed execute
                // make it so that when timeouttype expires, your function
                // is called with the freshest event
                curEvt = Evt;
                Evt.preventDefault();
        }
    };
};

Por defecto, esto acelera la función a, como máximo, una llamada cada 200 ms. Para cambiar el intervalo a una cantidad diferente de milisegundos, simplemente cambie el valor de minimumInterval .


Una forma de resolver este problema es definir un intervalo de tiempo y solo procesar un evento de desplazamiento una vez dentro de ese intervalo de tiempo. Si aparece más de un evento de desplazamiento durante ese intervalo de tiempo, lo ignorará y lo procesará solo cuando haya transcurrido ese intervalo de tiempo.

var scrollTimer, lastScrollFireTime = 0;

$(window).on('scroll', function() {

    var minScrollTime = 100;
    var now = new Date().getTime();

    function processScroll() {
        console.log(new Date().getTime().toString());
    }

    if (!scrollTimer) {
        if (now - lastScrollFireTime > (3 * minScrollTime)) {
            processScroll();   // fire immediately on first scroll
            lastScrollFireTime = now;
        }
        scrollTimer = setTimeout(function() {
            scrollTimer = null;
            lastScrollFireTime = new Date().getTime();
            processScroll();
        }, minScrollTime);
    }
});

Esto activará el primer evento de desplazamiento inmediatamente y luego obtendrá un evento de desplazamiento aproximadamente una vez cada 100 ms mientras se mueve la barra de desplazamiento y luego un evento final después de que la barra de desplazamiento deje de moverse. Puede ajustar la frecuencia del evento cambiando el argumento a setTimeout (lo que actualmente está configurado a 100).

Hay una demostración aquí: http://jsfiddle.net/jfriend00/EBEqZ/ que necesita para abrir una ventana de consola de depuración, comience a mover la barra de desplazamiento en la ventana de contenido y luego observe la hora de cada evento de desplazamiento en la ventana de la consola de depuración . En mi versión de Chrome, están configurados para un espaciado mínimo de 100 ms y parecen ocurrir cada 100-200 ms.


var isWorking = 0;

$(window).on('scroll', function()
{
    if(isWorking==0)  
    {
         isWorking=1;
         if (window.pageYOffset > loadMoreButton.offsetTop - 1000)
         # load more content via ajax
         setTimeout(function(){isWorking=0},1000);
    }
}

var now = new Date().getTime();
$(window).scroll( function () {
    if (window.pageYOffset > loadMoreButton.offsetTop - 1000)
    {
        if (new Date().getTime() - now > 1000)
        {
            console.log("Task executed once per second");
            now = new Date().getTime();
        }
    }
});

O

Puede utilizar llamadas de función de throttling-function-calls : llamadas de función de throttling-function-calls

function throttle(fn, threshhold, scope) {
  threshhold || (threshhold = 250);
  var last,
      deferTimer;
  return function () {
    var context = scope || this;

    var now = +new Date,
        args = arguments;
    if (last && now < last + threshhold) {
      // hold on to it
      clearTimeout(deferTimer);
      deferTimer = setTimeout(function () {
        last = now;
        fn.apply(context, args);
      }, threshhold);
    } else {
      last = now;
      fn.apply(context, args);
    }
  };
}

Puedes llamarlo así:

$('body').on('mousemove', throttle(function (event) {
  console.log('tick');
}, 1000));




javascript