Estoy ejecutando un setTimeout, de forma recursiva, por lo que solo quiero llamar a la API una vez por minuto.
Aquí está mi código:
;(async function ticker (minutes) { try { const res = await coingecko.global() const { market_cap_percentage } = res.data.data dominance = { btc: market_cap_percentage.btc, eth: market_cap_percentage.eth } console.log({ dominance }) } catch (ex) { console.log(ex.message) } finally { setTimeout(ticker, minutes * 60 * 1000) } })(1)El problema es:
Lo llama inmediatamente porque eso es lo que hace su código. Ejecuta la llamada a la función ticker(1) inmediatamente.
Cuando llama a ticker desde setTimeout(ticker, ...) , no está pasando el parámetro de minutes a esa función; es por eso que setTimeout() no se retrasa correctamente.
Si no desea que se ejecute de inmediato, deshágase del IIFE y simplemente inícielo con setTimeout() . Y, luego, cuando llame a ticker() desde la devolución de llamada setTimeout() , asegúrese de pasarle los argumentos de los minutes , ya sea pasando el tercer argumento a setTimeout() o haciendo una pequeña función de devolución de llamada para él.
Aquí hay una implementación:
async function ticker(minutes) { try { const res = await coingecko.global() const { market_cap_percentage } = res.data.data dominance = { btc: market_cap_percentage.btc, eth: market_cap_percentage.eth } console.log({ dominance }) } catch (ex) { console.log(ex.message) } finally { setTimeout(ticker, minutes * 60 * 1000, minutes); } } setTimeout(ticker, minutes * 60 * 1000, 1);¿Quizás solo necesitas usar algún administrador de horarios, como bree ?
A partir de su código
setTimeout(() => ticker(1), minutes * 60 * 1000)setTimeout de la misma manera para pasar el parámetro minutes , porque ahora solo pasa undefined . Eso significa immediately para setTimeout .ticker espera minutes como argumento, por lo que debe pasar los minutos cuando lo llame dentro de setTimeout . Además de eso, setTimeout espera una función en el primer argumento, por lo que sugiero simplemente pasar una función de flecha que llame a su función ticker . Por favor, compruebe el siguiente código:
;(async function ticker (minutes) { try { const res = await coingecko.global() const { market_cap_percentage } = res.data.data dominance = { btc: market_cap_percentage.btc, eth: market_cap_percentage.eth } console.log({ dominance }) } catch (ex) { console.log(ex.message) } finally { setTimeout(() => ticker(minutes), minutes * 60 * 1000) } })(1)Creo que la respuesta de jfriend00 ya resolvió el problema. En aras de la legibilidad, le aconsejo un enfoque menos funcional:
;(async function ticker (minutes) { while(true) { await new Promise(res => setTimeout(res, minutes * 60 * 1000)); try { const res = await coingecko.global() const { market_cap_percentage } = res.data.data dominance = { btc: market_cap_percentage.btc, eth: market_cap_percentage.eth } console.log({ dominance }) } catch (ex) { console.log(ex.message) } } })(1)Aquí hay una solución demasiado complicada y probablemente no adecuada, setInterval . Solo quería mostrar cómo podemos usar setInterval para lograr el mismo comportamiento.
const fetch = require('isomorphic-fetch') const url = 'https://jsonplaceholder.typicode.com/posts'; const closeThis = () => { let ids = []; async function executeThisShiz(minutes) { ids.forEach((id) => { clearInterval(id); }) try { let res = await fetch(url); res = await res.json(); console.log('yay') return res; } catch(e) { // maybe abort the timer idk? console.log('error', e); } finally { id = setInterval(() => { executeThisShiz(minutes); }, minutes*60*1000); ids.push(id); } } return { ids, executeThisShiz } } const {executeThisShiz} = closeThis(); executeThisShiz(0.1);Ya hay algunas buenas explicaciones aquí, pero voy a refactorizar un poco el código para aprovechar async/await sin necesidad de una biblioteca externa.
Primero, hagamos que setTimeout sea una función asíncrona:
async function sleep(ms) { return new Promise(res => setTimeout(res, ms)); } A continuación, usemos eso en lugar de setTimeout :
(async function ticker (minutes) { do { await sleep(minutes * 60 * 1000); await loadData(); } while (true); async function loadData() { try { const res = await coingecko.global() const { market_cap_percentage } = res.data.data dominance = { btc: market_cap_percentage.btc, eth: market_cap_percentage.eth } } catch (err) { console.error(ex.message); } } })(1)Esto funciona más o menos igual excepto
También es mucho más fácil de entender y leer, y dado que usa async/await, se adhiere a un solo paradigma (en lugar de usar async/await y devoluciones de llamada para setTimeout ).