texto strong poner negrita letra javascript ajax order-of-execution

javascript - poner - strong css



¿Cómo hacer que el código javascript se ejecute*en orden* (9)

Como han señalado otros, no desea realizar una operación sincrónica. Embrace Async, eso es lo que significa la A en AJAX.

Solo quisiera mencionar una excelente analogía en sincronización v / s asíncrono. Puedes leer la publicación completa en el foro de GWT , solo estoy incluyendo las analogías relevantes.

Imagina si quieres ...

Está sentado en el sofá mirando televisión y, sabiendo que no tiene cerveza, le pide a su cónyuge que, por favor, vaya a la tienda de licores y le traiga algo. Tan pronto como ve a su cónyuge salir por la puerta principal, se levanta del sofá, entra en la cocina y abre la nevera. Para tu sorpresa, no hay cerveza!

Bueno, por supuesto que no hay cerveza, su cónyuge todavía está en el viaje a la tienda de licores. Tienes que esperar hasta que regrese antes de que puedas esperar a tomar una cerveza.

Pero, ¿dices que lo quieres síncrono? Imagina otra vez ...

... el cónyuge sale por la puerta ... ahora, todo el mundo a tu alrededor se detiene, no respiras, respondes a la puerta o terminas de ver tu programa mientras corre por la ciudad a buscar tu cerveza. Solo tienes que sentarte allí sin mover un músculo y volverse azul hasta que pierdas el conocimiento ... despertándote un tiempo indefinido más tarde rodeado de EMT y un cónyuge que dicen "oh, hey, tengo tu cerveza".

Eso es exactamente lo que sucede cuando insistes en hacer una llamada al servidor sincrónico.

Bien, aprecio que Javascript no sea C # o PHP, pero sigo volviendo a un problema en Javascript, no con JS en sí, sino con mi uso.

Tengo una función:

function updateStatuses(){ showLoader() //show the ''loader.gif'' in the UI updateStatus(''cron1''); //performs an ajax request to get the status of something updateStatus(''cron2''); updateStatus(''cron3''); updateStatus(''cronEmail''); updateStatus(''cronHourly''); updateStatus(''cronDaily''); hideLoader(); //hide the ''loader.gif'' in the UI }

El problema es que, debido al deseo ardiente de Javascript de avanzar en el código, el cargador nunca aparece porque la función ''hideLoader'' se ejecuta inmediatamente después.

¿Cómo puedo arreglar esto? O, en otras palabras, ¿cómo puedo hacer que una función javascript se ejecute en el orden en que la escribo en la página ...


Debe pensar en JavaScript como un evento basado en lugar de un procedimiento si está realizando la programación AJAX. Debe esperar hasta que finalice la primera llamada antes de ejecutar la segunda. La forma de hacerlo es vincular la segunda llamada a una devolución de llamada que se activa cuando finaliza la primera. Sin saber más sobre el funcionamiento interno de su biblioteca AJAX (espero que esté usando una biblioteca) no puedo decirle cómo hacerlo, pero probablemente se verá algo como esto:

showLoader(); updateStatus(''cron1'', function() { updateStatus(''cron2'', function() { updateStatus(''cron3'', function() { updateStatus(''cronEmail'', function() { updateStatus(''cronHourly'', function() { updateStatus(''cronDaily'', funciton() { hideLoader(); }) }) }) }) }) }) });

La idea es que updateStatus toma su argumento normal, más una función de devolución de llamada que se ejecuta cuando se termina. Es un patrón bastante común para pasar una función para que se ejecute en onComplete en una función que proporciona tal gancho.

Actualizar

Si está utilizando jQuery, puede leer $.ajax() aquí: http://api.jquery.com/jQuery.ajax/

Su código probablemente se ve algo como esto:

function updateStatus(arg) { // processing $.ajax({ data : /* something */, url : /* something */ }); // processing }

Puede modificar sus funciones para tomar una devolución de llamada como su segundo parámetro con algo como esto:

function updateStatus(arg, onComplete) { $.ajax({ data : /* something */, url : /* something */, complete : onComplete // called when AJAX transaction finishes });

}


El problema se produce porque AJAX está en su naturaleza asíncrono. Esto significa que las llamadas a updateStatus() se ejecutan de hecho en orden, pero se devuelven inmediatamente y el intérprete de JS llega a hideLoader() antes de que los datos se recuperen de las solicitudes de AJAX.

Debería realizar el hideLoader() en un evento en el que las llamadas AJAX hayan finalizado.


Esto no tiene nada que ver con el orden de ejecución del código.

La razón por la que la imagen del cargador nunca se muestra, es que la interfaz de usuario no se actualiza mientras se ejecuta la función. Si realiza cambios en la interfaz de usuario, no aparecerán hasta que salga de la función y devuelva el control al navegador.

Puede usar un tiempo de espera después de configurar la imagen, lo que le brinda al navegador la oportunidad de actualizar la interfaz de usuario antes de iniciar el resto del código:

function updateStatuses(){ showLoader() //show the ''loader.gif'' in the UI // start a timeout that will start the rest of the code after the UI updates window.setTimeout(function(){ updateStatus(''cron1''); //performs an ajax request to get the status of something updateStatus(''cron2''); updateStatus(''cron3''); updateStatus(''cronEmail''); updateStatus(''cronHourly''); updateStatus(''cronDaily''); hideLoader(); //hide the ''loader.gif'' in the UI },0); }

Hay otro factor que también puede hacer que su código parezca que se ejecuta fuera de orden. Si sus solicitudes de AJAX son asíncronas, la función no esperará las respuestas. La función que se encarga de la respuesta se ejecutará cuando el navegador reciba la respuesta. Si desea ocultar la imagen del cargador después de que se haya recibido la respuesta, tendrá que hacerlo cuando se ejecute la última función del controlador de respuesta. Como las respuestas no tienen que llegar en el orden en que enviaste las solicitudes, deberías contar cuántas respuestas debes saber cuando llega la última.


Instale Firebug, luego agregue una línea como esta a cada uno de showLoader, updateStatus y hideLoader:

Console.log("event logged");

Verá en la ventana de la consola las llamadas a su función, y estarán en orden. La pregunta es, ¿qué hace su método "updateStatus"?

Es de suponer que inicia una tarea en segundo plano, luego regresa, por lo que llegará a la llamada a hideLoader antes de que finalice cualquiera de las tareas en segundo plano. Su biblioteca Ajax probablemente tiene una devolución de llamada "OnComplete" o "OnFinished": llame al siguiente estado de actualización desde allí.


Mueve las llamadas a updateStatus a otra función. realice una llamada a setTimeout con la nueva función como destino.

Si sus solicitudes de ajax son asíncronas, debe tener algo para rastrear cuáles se han completado. Cada método de devolución de llamada puede establecer un indicador "completado" en algún lugar por sí mismo y verificar si es el último en hacerlo. si es así, entonces haz que llame a hideLoader.


Pienso que todo lo que necesitas hacer es tener esto en tu código:

async: false,

Entonces tu llamada Ajax se vería así:

jQuery.ajax({ type: "GET", url: "something.html for example", dataType: "html", async: false, context: document.body, success: function(response){ //do stuff here }, error: function() { alert("Sorry, The requested property could not be found."); } });

Obviamente, parte de esta necesidad de cambiar para XML , JSON , etc. pero async: false, es el punto principal aquí que le dice al motor JS que espere hasta que la llamada exitosa haya regresado (o haya fallado dependiendo) y luego continúe. Recuerde que hay un inconveniente en esto, y eso es que toda la página deja de responder hasta que el ajax regrese. por lo general, en milisegundos, lo que no es un gran problema, pero PODRÍA tardar más tiempo.

Espero que esta sea la respuesta correcta y te ayude :)


Tenemos algo similar en uno de nuestros proyectos, y lo resolvimos usando un contador. Si aumenta el contador para cada llamada a updateStatus y lo reduce en la función de respuesta de la solicitud AJAX (depende de la biblioteca de JavaScript AJAX que esté usando).

Una vez que el contador llega a cero, se completan todas las solicitudes de AJAX y puede llamar a hideLoader() .

Aquí hay una muestra:

var loadCounter = 0; function updateStatuses(){ updateStatus(''cron1''); //performs an ajax request to get the status of something updateStatus(''cron2''); updateStatus(''cron3''); updateStatus(''cronEmail''); updateStatus(''cronHourly''); updateStatus(''cronDaily''); } function updateStatus(what) { loadCounter++; //perform your AJAX call and set the response method to updateStatusCompleted() } function updateStatusCompleted() { loadCounter--; if (loadCounter <= 0) hideLoader(); //hide the ''loader.gif'' in the UI }


Una de las mejores soluciones para manejar todas las solicitudes asíncronas es la ''Promesa'' .
El objeto Promesa representa la finalización (o falla) eventual de una operación asíncrona.

Ejemplo:

let myFirstPromise = new Promise((resolve, reject) => { // We call resolve(...) when what we were doing asynchronously was successful, and reject(...) when it failed. // In this example, we use setTimeout(...) to simulate async code. // In reality, you will probably be using something like XHR or an HTML5 API. setTimeout(function(){ resolve("Success!"); // Yay! Everything went well! }, 250); }); myFirstPromise.then((successMessage) => { // successMessage is whatever we passed in the resolve(...) function above. // It doesn''t have to be a string, but if it is only a succeed message, it probably will be. console.log("Yay! " + successMessage); });

Promise

Si tiene 3 funciones asíncronas y espera ejecutarlas en orden, haga lo siguiente:

let FirstPromise = new Promise((resolve, reject) => { FirstPromise.resolve("First!"); }); let SecondPromise = new Promise((resolve, reject) => { }); let ThirdPromise = new Promise((resolve, reject) => { }); FirstPromise.then((successMessage) => { jQuery.ajax({ type: "type", url: "url", success: function(response){ console.log("First! "); SecondPromise.resolve("Second!"); }, error: function() { //handle your error } }); }); SecondPromise.then((successMessage) => { jQuery.ajax({ type: "type", url: "url", success: function(response){ console.log("Second! "); ThirdPromise.resolve("Third!"); }, error: function() { //handle your error } }); }); ThirdPromise.then((successMessage) => { jQuery.ajax({ type: "type", url: "url", success: function(response){ console.log("Third! "); }, error: function() { //handle your error } }); });

Con este enfoque, puede manejar todas las operaciones asíncronas como desee.