[Resuelto] [Pregunta]: ¿Como hacer que un timer me devuelva un valor?

Iniciado por Leguim, 14 Septiembre 2019, 13:49 PM

0 Miembros y 1 Visitante están viendo este tema.

Leguim

Buenos días,
estaba  haciendo un pequeño sistema y me encuentro con un problema, es que no consigo que un 'timeout' me devuelva un valor.

Código (javascript) [Seleccionar]

<button type="button" onclick="Correr_Funcion();">Presionar</button>
<script type="text/javascript">
var estado = false;

function Correr_Funcion()
{
console.log(estado);

if(estado == false)
{
estado = true;
estado = setTimeout(TimerEx, 4000);
}
else
{
console.log('AGUANTA WUACHIN');
}
}

function TimerEx()
{
console.log('La función cargo correctamente!');
return false;
}
</script>


Tengo conciencia que esto podría ser reemplazado donde en 'TimerEx()' dice return false; por estado = false; y en 'Correr_Funcion()' estado = setTimeout reemplazar por sólo setTimeout. Eso resolvería el problema, pero necesitaba que el timer me devolviera/retorne x valor y la deposite en una variable.

MinusFour

Si te das cuenta setTimeout ya devuelve un valor. Es el identificador del timer. La realidad es que no hay forma de regresar un valor en una función que se ejecuta después. Lo más cercano a esto es: await.

Código (javascript) [Seleccionar]


function miFuncion(){
   //han pasado 3000 msecs desde que la función setTimeout se llamo
   //miFuncion hace algo importante aquí y lo guarda en una variable
   let miValorImportante = 'muyimportante';
   //puedo trabajar con el valor importante de aquí en adelante.
}

setTimeout(miFuncion, 3000);


Para que entiendas mejor, el runtime de JS lo va a procesar así:

1. El runtime ve la declaración de la función, evalua, hace el hoisting, etc, etc.
2. Se ejecuta la función setTimeout y le dice al runtime: "En 3 segundos corre la función miFuncion".
3. Pasan 3 segundos y el runtime corre la función miFuncion
4. La función genera el valor que es importante para seguir el script.

Es imposible que setTimeout regrese un valor que se calcula después.

Si tu quieres trabajar con ese valor, la única forma es trabajarlo desde ese punto, tal y como lo comente en el script. Por ejemplo, puedes crear otra función fuera y llamarla desde la función agendada por setTimeout:

Código (javascript) [Seleccionar]


function procesaValorImportante(importante){
    //sigo procesando el valor muy importante
}

function miFuncion(){
   //han pasado 3000 msecs desde que la función setTimeout se llamo
   //miFuncion hace algo importante aquí y lo guarda en una variable
   let miValorImportante = 'muyimportante';
   //puedo trabajar con el valor importante de aquí en adelante.
   procesaValorImportante(miValorImportante);
}

setTimeout(miFuncion, 3000);


Y así sigues el flujo de tu script, dentro de la función. Se vuelve un poco complicado manejar el flujo de está manera porque lo tienes que continuar desde la función.

Para eso se inventaron las promesas. Una promesa es simplemente un objeto que maneja un valor eventual. No todas las APIs asincronas manejan promesas, para eso puedes usar el constructor de las promesas:

Código (javascript) [Seleccionar]

let timeoutP = function(ms){
    return new Promise(function(f, r){ setTimeout(f, ms);  });
};


Y para usarlo es muy sencillo:

Código (javascript) [Seleccionar]

let miValorImportante = timeoutP(3000).then(function(){ /* han pasado 3000 msecs desde entonces */ return 'muyimportante' });
importanteP.then(function(importante){ importante == 'muyImportante' });


Y finalmente, como ya trabajamos con promesas podemos usar async/await (nada más considera que quizás no todos los navegadores soportan este syntax).

Código (javascript) [Seleccionar]

async function miFuncion(){
    await timeoutP(3000);
    //3000 msecs han pasado
    let miValorImportante = 'muyimportante';
};

miFuncion();

Leguim