Tengo dos funciones JS. Uno llama al otro. Dentro de la función de llamada, me gustaría llamar a la otra, esperar a que termine esa función y luego continuar. Entonces, por ejemplo / pseudocódigo:
function firstFunction(){
for(i=0;i<x;i++){
// do something
}
};
function secondFunction(){
firstFunction()
// now wait for firstFunction to finish...
// do something else
};
Se me ocurrió esta solución, pero no sé si es una forma inteligente de hacerlo.
var isPaused = false;
function firstFunction(){
isPaused = true;
for(i=0;i<x;i++){
// do something
}
isPaused = false;
};
function secondFunction(){
firstFunction()
function waitForIt(){
if (isPaused) {
setTimeout(function(){waitForIt()},100);
} else {
// go do that thing
};
}
};
¿Es eso legítimo? ¿Hay alguna forma más elegante de manejarlo? Quizás con jQuery?
firstFunction
exactamente eso lo hace asíncrono? De cualquier manera - verifique las promesasRespuestas:
Una forma de lidiar con el trabajo asincrónico como este es usar una función de devolución de llamada, por ejemplo:
Según la sugerencia de @Janaka Pushpakumara, ahora puede usar las funciones de flecha para lograr lo mismo. Por ejemplo:
firstFunction(() => console.log('huzzah, I\'m done!'))
Actualización: respondí esto hace bastante tiempo, y realmente quiero actualizarlo. Si bien las devoluciones de llamada son absolutamente buenas, en mi experiencia tienden a generar un código que es más difícil de leer y mantener. Sin embargo, hay situaciones en las que todavía los uso, como pasar eventos en progreso y similares como parámetros. Esta actualización es solo para enfatizar las alternativas.
También la pregunta original no menciona specificallty asíncrona, por lo que en caso de que alguien se confunde, si su función es sincrónico, que se bloquean cuando se le llama. Por ejemplo:
Si, como está implícito, la función es asíncrona, la forma en que tiendo a lidiar con todo mi trabajo asincrónico hoy es con async / wait. Por ejemplo:
En mi opinión, async / await hace que su código sea mucho más legible que usar promesas directamente (la mayoría de las veces). Si necesita manejar errores de captura, úselo con try / catch. Lea más sobre esto aquí: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function .
fuente
Use async / await:
luego use await en su otra función para esperar a que regrese:
fuente
$(function() { await firstFunction(); secondFunction(); });
,?await
que solo se puede usar dentro de unasync
método. Entonces, si hace que su función principalasync
pueda llamar a todos los que esténasync methods
dentro con o sinawait
eso, lo desea.await
unasetTimeout
?Parece que te estás perdiendo un punto importante aquí: JavaScript es un entorno de ejecución de subproceso único. Veamos nuevamente su código, tenga en cuenta que he agregado
alert("Here")
:No tienes que esperar
isPaused
. Cuando vea la alerta "Aquí",isPaused
seráfalse
ya, yfirstFunction
se han devuelto. Esto se debe a que no puede "ceder" desde el interior delfor
bucle (// do something
), es posible que el bucle no se interrumpa y tendrá que completarse primero primero (más detalles: manejo de hilos Javascript y condiciones de carrera ).Dicho esto, aún puede hacer que el código fluya
firstFunction
para que sea asíncrono y usar la devolución de llamada o la promesa de notificar a la persona que llama. Tendría que renunciar alfor
bucle y simularlo conif
( JSFiddle ):En una nota al margen, JavaScript 1.7 ha introducido
yield
palabras clave como parte de los generadores . Eso permitirá "perforar" agujeros asincrónicos en el flujo de código JavaScript sincrónico ( más detalles y un ejemplo ). Sin embargo, el soporte del navegador para generadores está actualmente limitado a Firefox y Chrome, AFAIK.fuente
Una manera elegante de esperar a que una función se complete primero es usar Promises con la función async / await .
setTimeout
demostrar la situación en la que las instrucciones tardarían un tiempo en ejecutarse.await
la primera función antes de continuar con las instrucciones.Ejemplo:
Nota:
Usted podría simplemente
resolve
elPromise
sin ningún valor como talresolve()
. En mi ejemplo, tengoresolved
elPromise
valory
que puedo usar en la segunda función.fuente
El único problema con las promesas es que IE no las admite. Edge sí, pero hay muchos IE 10 y 11: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise (compatibilidad en la parte inferior)
Entonces, JavaScript es de un solo subproceso. Si no está haciendo una llamada asincrónica, se comportará de manera predecible. El hilo principal de JavaScript ejecutará una función por completo antes de ejecutar la siguiente, en el orden en que aparecen en el código. Garantizar el orden de las funciones síncronas es trivial: cada función se ejecutará completamente en el orden en que se llamó.
Piense en la función síncrona como una unidad atómica de trabajo. . El hilo principal de JavaScript lo ejecutará completamente, en el orden en que aparecen las declaraciones en el código.
Pero, agregue la llamada asincrónica, como en la siguiente situación:
Esto no hace lo que quieres . Ejecuta instantáneamente la función 1, la función 2 y la función 3. La carga de div parpadea y desaparece, mientras que la llamada ajax no está casi completa, aunque
makeAjaxCall()
haya regresado. LA COMPLICACIÓN es quemakeAjaxCall()
ha dividido su trabajo en trozos que avanzan poco a poco por cada giro del hilo principal de JavaScript : se está comportando de manera astronómica. Pero ese mismo hilo principal, durante una vuelta / ejecución, ejecutó las partes síncronas de forma rápida y previsible.Entonces, la forma en que lo manejé : como dije, la función es la unidad atómica de trabajo. Combiné el código de la función 1 y 2: puse el código de la función 1 en la función 2, antes de la llamada asíncrona. Me deshice de la función 1. Todo, incluida la llamada asincrónica, se ejecuta de manera predecible, en orden.
ENTONCES, cuando la llamada asincrónica se completa, después de varios giros del hilo principal de JavaScript, haga que llame a la función 3. Esto garantiza el orden . Por ejemplo, con ajax, el controlador de eventos onreadystatechange se llama varias veces. Cuando informa que se ha completado, llame a la función final que desee.
Estoy de acuerdo que es más desordenado. Me gusta que el código sea simétrico, me gusta que las funciones hagan una cosa (o casi), y no me gusta que la llamada ajax sea responsable de la pantalla (creando una dependencia en la persona que llama). PERO, con una llamada asincrónica incrustada en una función síncrona, se deben hacer compromisos para garantizar el orden de ejecución. Y tengo que codificar para IE 10, así que no hay promesas.
Resumen : para llamadas síncronas, garantizar el orden es trivial. Cada función se ejecuta completamente en el orden en que se llamó. Para una función con una llamada asincrónica, la única forma de garantizar el orden es monitorear cuando se completa la llamada asincrónica y llamar a la tercera función cuando se detecta ese estado.
Para una discusión de los hilos de JavaScript, consulte: https://medium.com/@francesco_rizzi/javascript-main-thread-dissected-43c85fce7e23 y https://developer.mozilla.org/en-US/docs/Web/JavaScript/ EventLoop
Además, otra pregunta similar y altamente calificada sobre este tema: ¿Cómo debo llamar a 3 funciones para ejecutarlas una tras otra?
fuente
Esto es lo que se me ocurrió, ya que necesito ejecutar varias operaciones en una cadena.
fuente
Su diversión principal llamará primeroDiversión y luego, al completarla, llamará su próxima diversión.
fuente