Me siento estúpido porque no encuentro lo que quiero hacer...
Está en PURO Javascript.
Quiero llamar a una función y detenerla (o eliminarla, o lo que sea) en unos segundos.
Aquí está mi código real:
function scrollThumbnails() { const thumbnails = document.querySelectorAll('.thumbnail'); for (thumbnail of thumbnails) { thumbnail.classList.add('active'); await verticalSlider(thumbnail); resetSliderPosition(thumbnail); thumbnail.classList.remove('active'); } scrollThumbnails(); } async function verticalSlider(element) { const slider = element.querySelector('.vertical-carrousel'); const max = slider.offsetHeight - slider.parentElement.offsetHeight; var toTop = 0; while (toTop > -max) { await new Promise((resolve) => setTimeout(resolve, 50)); toTop--; slider.style.top = toTop + 'px'; } await new Promise((resolve) => setTimeout(resolve, 1000)); } function resetSliderPosition(element) { const slider = element.querySelector('.vertical-carrousel'); slider.style.removeProperty('top'); }Así que aquí, quiero llamar a 'verticalSlider' en mi bucle, pero si dura más de 45 segundos, quiero detenerlo y pasar a la siguiente miniatura.
Es posible ? ¿Echo de menos algo?
Gracias por avanzado :)
Este es un ejemplo simple sin async y await con la implementación del contador de tiempo de espera manual.
// Function, which accepts time out value in seconds (counting from 0) const myFunct = (timeOutSec) => { // Get current time const ct = Date.now(); // Set counter for example function logic let secCounter = ct - 1000; // Start eternal loop while(true) { // Get in loop time const ilt = Date.now(); // Compare current time and in loop time // If current time + timeout sec < in loop time, break it if(ct + timeOutSec * 1000 < ilt) break; // Here do main function logic in loop // for example, console log each second if(ilt - secCounter > 1000) { console.log(`time ${ilt}`); secCounter += 1000; } } } // Test running function for 4 sec myFunct(3); console.log(`Completed at ${Date.now()}`);O similar con promesas
// Async timeout function const timeout = (ms) => new Promise(resolve => setTimeout(resolve, ms)); // Promise function which accepts timout value in seconds (counting from 0) const myPFunct = (timeOutSec) => { return new Promise(async (resolve, reject) => { // Current time const ct = Date.now(); // start eternal loop while(true) { // In loop time const ilt = Date.now(); // Check in-loop time, current time and timeout if(ct + timeOutSec * 1000 < ilt) { resolve(`completed at ${ilt}`); break; } // Do something console.log(`time: ${ilt}`); // Wait 1 sec await timeout(1000); } }); } // Test async function const test = async () => { // Run myPFunct for 4 sec const result = await myPFunct(3); console.log(`Test function result: ${result}`); } // Run test function test();Gracias a la solución de @tarkh. Si alguien intenta hacer un control deslizante horizontal como yo, o algo con bucle, tengo que modificar el código (porque con la solución de origen, la resolución aumenta a todos los métodos asíncronos).
Aquí está la solución final (tengo que nombrar el ciclo para romperlo y resolver la promesa actual; ¿quizás haya una solución más simple?):
window.onload = function () { scrollThumbnails(); } const scrollThumbnails = async () => { const thumbnails = document.querySelectorAll('.thumbnail'); for (thumbnail of thumbnails) { thumbnail.classList.add('active'); await verticalSliderWithTimeout(thumbnail, 45000); thumbnail.classList.remove('active'); } scrollThumbnails(); } const timeout = (ms) => new Promise(resolve => setTimeout(resolve, ms)); const verticalSliderWithTimeout = (element, timeoutDelay) => { return new Promise(async (resolve, reject) => { const currentTime = Date.now(); const slider = element.querySelector('.vertical-carrousel'); const max = slider.offsetHeight - slider.parentElement.offsetHeight; var toTop = 0; slider.style.top = toTop + 'px'; sliderLoop: while (toTop > -max) { const inLoopTime = Date.now(); if(currentTime + timeoutDelay < inLoopTime) { break sliderLoop; } await timeout(50); toTop--; slider.style.top = toTop + 'px'; } resolve(); }); }Código HTML si es necesario (Manillares):
<div class="thumbnail"> <div class="photos-slider"> <div id="vertical-carrousel" class="vertical-carrousel"> {{#each this.photos}} <img src="/image/{{../this.agency.product_type}}/{{../this.agency.id}}/{{../this.reference}}/{{urlencode this}}" onerror="{{this}}" /> {{/each}} </div> </div> </div>