while infinito funciones for ejemplos ejemplo ciclo bucle javascript asynchronous callback theory synchronous

javascript - infinito - Función asincrónica en un ciclo while



do while javascript ejemplo (5)

En javascript, no puede bucle esperar a que cambie una condición a menos que el código que realmente cambia la condición esté dentro de ese mismo bucle o un efecto secundario de alguna función llamada en el bucle. Esto se debe a que javascript tiene un único hilo (excepto para los webworkers que no se consideran aquí) de modo que mientras un bucle esté en javascript, no se podrá ejecutar ningún otro código, por lo que ningún otro código podrá cambiar la variable de condición. Simplemente tendrá un ciclo infinito mientras el ciclo espera algo que nunca puede cambiar. Finalmente, el navegador se quejará de que tiene un código que no responde y se apagará.

Debido a eso, no hay bucles de espera indeterminados o largos en javascript. Es posible hacer un bucle por un segundo o más para dejar pasar un poco de tiempo, pero eso rara vez es útil, productivo o la mejor manera de escribir código JS.

En su lugar, debe activar un evento o una devolución de llamada cuando la condición cambia y el código interesado puede suscribirse a ese evento o registrar su devolución de llamada. O bien, debe sondear un temporizador para ver cuál ha cambiado la condición (la primera opción es la opción preferida).

Si estuvieras diseñando una API en la que quisieras permitir que algún código de llamada supiera cuándo cambia un estado, generalmente implementarías una devolución de llamada o una promesa. El enfoque de devolución de llamada podría verse así:

device.registerStateChangeCallback("type of state interested in", fn);

Luego, la API llamará a la función de devolución de llamada transferida cada vez que el estado especificado cambie a un nuevo valor. Depende de la API si esta es una notificación única o si ocurre cada vez que el estado cambia hasta que se cancela la cancelación de la devolución de llamada.

Entonces, en lugar de que la persona que llama espere en un bucle ocupado hasta que cambie el estado, la persona que llama escribe el código asíncrono (así es como funciona JavaScript para este tipo de cosas) con una devolución de llamada que se llamará más tarde cuando cambie el estado. Por ejemplo, el código de una persona que llama podría verse así:

device.registerStateChangeCallback("syncState", function(newState) { // caller puts code here that wants to do something when // the syncState has changed });

Si las notificaciones están destinadas a ser de una sola vez, entonces también puede usar promesas y la API simplemente devuelve una promesa que se resuelve cuando el syncState cambia:

device.registerStateChange("syncState").then(function(newState) { // caller puts code here that wants to do something when // the syncState has changed });

Las desventajas de las promesas son que son de uso exclusivo (solo una notificación), por lo que si desea recibir notificaciones múltiples, entonces es mejor utilizar las devoluciones de llamada. Las ventajas de las promesas sobre devoluciones de llamadas es que proporcionan muchas funciones para sincronizarlas con otros eventos (como la secuenciación, la espera de una serie de eventos para finalizar, la coordinación de varias cosas asincrónicas, etc.) y proporcionan una mejor sincronización. manejo de errores.

Tengo una pregunta sobre cómo realizar una tarea asíncrona en un ciclo while hasta que se cumpla alguna condición. Esta es más una pregunta teórica, pero puedo ver cómo esto podría ser un problema en algunos escenarios.

Trataré de demostrar el problema con un ejemplo (estoy usando JavaScript aquí, pero puedes usar cualquier idioma):

Podría tener un dispositivo y quiero retener mi aplicación hasta que ese dispositivo haya alcanzado un estado específico. Si el método con el que puedo getrieve con el estado del dispositivo es synchronouse, el código podría verse así:

// Hold until the desired state is reached var state = false; while (!state) { state = device.getStateSync(); } // [...] continue the program

Mi pregunta ahora es: ¿cómo puedo transformar este código cuando todo lo que obtengo del dispositivo es una función getState asincrónica? El código debería funcionar sin importar el tiempo de ejecución de la llamada y debe tener en cuenta que estoy trabajando con memoria limitada y tamaño de pila.

// [...] This would call the async function in a loop and crash the program while (!state) { // [...] something device.getStateAsync(function(newState) { state = newState; }); // [...] something else }

Esta publicación que encontré tiene una solución recursiva ( http://blog.victorquinn.com/javascript-promise-while-loop ). Si bien esta es una buena solución, en algún momento se encontrará con problemas de tamaño de pila, si el ciclo se llama con demasiada frecuencia.

En este momento, tengo la corazonada de que no podría haber una solución. ¿Conoces alguna forma de hacer esto? ¿O sabes cómo demostrar que no hay forma de hacerlo? Siéntase libre de incluir conceptos más complejos como Hilos, Promesas o Futuros.

Tenga en cuenta que esta es una pregunta teórica y el ejemplo es para una situación en la que no tengo forma de cambiar el marco (o dispositivo) con el que estoy trabajando.

Gracias por cada respuesta e idea!

Pedro


Esta es de hecho una pregunta muy teórica. Sería bastante extraño tener una API asíncrona para obtener un estado actual. Lo más probable es que tengas:

  • un método de sincronización que le proporciona el estado actual;
  • o un método asíncrono que te devolverá la llamada cuando cambie el estado. En ese caso, no es necesario bucle, solo espere la devolución de llamada.

Pero si tiene un ejemplo específico de dicha API, infórmenos ...


Esta función usa setTimeout para que la devolución de llamada regrese sin recurrencia. El requisito es que su entorno implemente un mecanismo setTimeout, ya que no es parte de JavaScript.

var callback = function callback(result){ if(result == "some condition"){ //done } else { setTimeout(device.getStateAsync(callback), 10); } } device.getStateAsync(callback);


No puedes hacer esto. La razón es que Javascript tiene un solo subproceso. Mientras se ejecuta el ciclo while, no se ejecuta nada más, por lo que cualquier tarea asíncrona que se espera que actualice el estado del dispositivo nunca tendrá la oportunidad de ejecutarse. Las tareas asíncronas en Javascript se ejecutan mediante el bucle de controlador de eventos principal. Esto significa que las operaciones de sincronización no se ejecutarán hasta que regrese de su script al controlador de eventos, o la secuencia de comandos realice una llamada al controlador de eventos (esto solo ocurre cuando la secuencia de comandos espera la entrada del usuario con confirm o prompt ).


Sé que esto llega tarde pero es6 ha proporcionado una mejor manera de hacer esto. La solución está en utilizar Generators + Promises .

Eche un vistazo a este repositorio donde tuve que crear subprocesos de Twitter donde el tuit anterior tiene que responder al anterior y usarlo, y esto se hace obteniendo el ID del tweet actual y usándolo para publicar el siguiente tweet.

Mira aquí => https://github.com/Udokah/tweet-threader