javascript - loop - Fuerza a setTimeout a disparar su carga útil antes de lo establecido originalmente
settimeout mdn (4)
He desarrollado una pequeña parte del software de presentación que consta de diapositivas y elementos para cada diapositiva. Cuando se procesa una diapositiva, todos sus activos se reparten en bucle y se procesan después de un retraso utilizando el método setTimeout
. se ve dulce
Yaaay !, los requisitos han cambiado, ahora se requiere que la presentación actúe como una presentación de diapositivas de PowerPoint, el evento de clic del mouse hará que el siguiente recurso se presente en la página de inmediato.
Mi pregunta es; ¿hay una manera de hacer que mi tiempo de espera se dispare inmediatamente? Puedo obtener y almacenar en una pila el timeoutid tal como se devuelve cuando se crea el timeout. La única otra opción sería cancelar el tiempo de espera y luego recrear el elemento, que es un proceso mucho más de lo que quiero hacer, y no tengo ganas de refactorizar mi código demasiado.
¿Algunas ideas?
Acabo de encontrar esta pregunta y terminé escribiendo una clase de conveniencia para manejar esto (usando es6, así que necesitarás transpilarlo para compatibilidad con versiones anteriores):
class Animations {
constructor() {
this.queue = [];
this.nextId = 0;
}
add(fn, delay) {
let id = this.nextId++;
let timeout = window.setTimeout(() => {
this.queue = this.queue.filter(d => d.id !== id);
fn();
}, delay);
this.queue.push({ id, fn, timeout });
return id;
}
flush() {
this.queue.forEach(d => {
window.clearTimeout(d.timeout);
d.fn();
});
this.queue = [];
}
}
export default Animations;
Luego, en lugar de usar setTimeout, uso una instancia de la clase de Animaciones para administrar todo el estado y me permite establecerTimeouts a través del .add(fn, delay)
, pero puedo forzar a los pendientes para que se ejecuten a través de .flush()
.
import Animations from ''./animations'';
let anims = new Animations();
anims.add(() => {
someElt.classList.add(''some-class'');
}, 1000);
// then, whenever you want to force it execute immediately
anims.flush();
La respuesta corta es No. No puede hacer lo que está pidiendo, a menos que mantenga una lista de los métodos a ser despedidos. A continuación, puede cancelar el temporizador y activar el método correspondiente.
Podrías envolverlo en un cierre como este:
function createTimeout(timeoutHandler, delay) {
var timeoutId;
timeoutId = setTimeout(timeoutHandler, delay);
return {
clear: function() {
clearTimeout(timeoutId);
},
trigger: function() {
clearTimeout(timeoutId);
return timeoutHandler();
}
};
}
var a = new Date();
var timeout = createTimeout(function() { console.log(a); }, 1000);
// timeout.clear();
timeout.trigger();
Si configura el temporizador de esta manera:
var timer1 = window.setTimeout(mainFunction,500)
llámalo inmediatamente haciendo esto:
window.clearTimeout(timer1)
mainFunction()
La clave es separar la función del temporizador.