lgados
He desarrollado un pequeño software de presentación que consta de diapositivas y activos para cada diapositiva. Cuando se procesa una diapositiva, todos sus activos se repiten y se procesan después de un retraso utilizando el setTimeout
método. 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 activo se represente en la página de inmediato.
Mi pregunta es; ¿Hay alguna 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 tiempo de espera. La única otra opción sería cancelar el tiempo de espera y luego volver a crear el elemento, que es mucho más procesamiento de lo que quiero hacer, y no tengo ganas de refactorizar demasiado mi código.
¿Algunas ideas?
Killroy
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();
Actualizado (js moderno):
let newTimeout = (handler, delay) => {
let id = setTimeout(handler, delay), clear = clearTimeout.bind(null, id);
return {id, clear, trigger: () => (clear(), handler())};
};
let timeout = newTimeout(() => console.log(new Date()), 1000);
// timeout.clear();
timeout.trigger();
-
solución elegante
– Joba Diniz
18 de agosto de 2017 a las 12:09
-
O, más moderno:
var createTimeout = (handler, delay) => { var id = setTimeout(handler, delay), clear = () => clearTimeout(id); return {clear, restart: (newDelay) => (clear(), (id = setTimeout(handler, newDelay || delay))), trigger: () => (clear(), handler())} };
– Killroy
24 de agosto de 2020 a las 8:51
Diodeo – James MacFarlane
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.
-
caca, pensé que tendría que hacer esto, esperaba una solución rápida. Como la ‘función principal’ tiene argumentos calculados cuando se establece el tiempo de espera por primera vez, tendré que hacer una refactorización para que aparezcan en el evento onlick… muchas gracias
– lgados
7 oct 2011 a las 15:49
-
Vea mi respuesta a continuación para un envoltorio de cierre que evita tener que administrar más cosas. Reemplaza timeoutId con un objeto con un método .cancel() y .trigger().
– Killroy
22 de abril de 2016 a las 9:33
La respuesta corta es No. No puede hacer lo que pide, a menos que mantenga una lista de los métodos que se van a despedir. A continuación, puede cancelar el temporizador y activar el método correspondiente.
Acabo de encontrarme con esta pregunta y terminé escribiendo una clase de conveniencia para manejar esto (usando es6, por lo que deberá 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 Animations para administrar todo el estado y me permite configurar los tiempos de espera a través de la .add(fn, delay)
método, pero puedo forzar que los pendientes 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();