Foro de elhacker.net

Programación => Desarrollo Web => Mensaje iniciado por: Leguim en 14 Septiembre 2019, 13:49 pm



Título: [Resuelto] [Pregunta]: ¿Como hacer que un timer me devuelva un valor?
Publicado por: Leguim en 14 Septiembre 2019, 13:49 pm
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
  1. <button type="button" onclick="Correr_Funcion();">Presionar</button>
  2. <script type="text/javascript">
  3. var estado = false;
  4.  
  5. function Correr_Funcion()
  6. {
  7. console.log(estado);
  8.  
  9. if(estado == false)
  10. {
  11. estado = true;
  12. estado = setTimeout(TimerEx, 4000);
  13. }
  14. else
  15. {
  16. console.log('AGUANTA WUACHIN');
  17. }
  18. }
  19.  
  20. function TimerEx()
  21. {
  22. console.log('La función cargo correctamente!');
  23. return false;
  24. }
  25. </script>
  26.  

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.


Título: Re: [Pregunta]: ¿Como hacer que un timer me devuelva un valor?
Publicado por: MinusFour en 14 Septiembre 2019, 16:24 pm
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
  1.  
  2. function miFuncion(){
  3.   //han pasado 3000 msecs desde que la función setTimeout se llamo
  4.   //miFuncion hace algo importante aquí y lo guarda en una variable
  5.   let miValorImportante = 'muyimportante';
  6.   //puedo trabajar con el valor importante de aquí en adelante.
  7. }
  8.  
  9. 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
  1.  
  2. function procesaValorImportante(importante){
  3.    //sigo procesando el valor muy importante
  4. }
  5.  
  6. function miFuncion(){
  7.   //han pasado 3000 msecs desde que la función setTimeout se llamo
  8.   //miFuncion hace algo importante aquí y lo guarda en una variable
  9.   let miValorImportante = 'muyimportante';
  10.   //puedo trabajar con el valor importante de aquí en adelante.
  11.   procesaValorImportante(miValorImportante);
  12. }
  13.  
  14. 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
  1. let timeoutP = function(ms){
  2.    return new Promise(function(f, r){ setTimeout(f, ms);  });
  3. };

Y para usarlo es muy sencillo:

Código
  1. let miValorImportante = timeoutP(3000).then(function(){ /* han pasado 3000 msecs desde entonces */ return 'muyimportante' });
  2. 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
  1. async function miFuncion(){
  2.    await timeoutP(3000);
  3.    //3000 msecs han pasado
  4.    let miValorImportante = 'muyimportante';
  5. };
  6.  
  7. miFuncion();
  8.  


Título: Re: [Pregunta]: ¿Como hacer que un timer me devuelva un valor?
Publicado por: Leguim en 14 Septiembre 2019, 16:52 pm
Gracias! voy a revisar el código.