Cómo hacer que el código espere al llamar a llamadas asincrónicas como Ajax [duplicado]

101

Estoy buscando algo como esto

function someFunc() {

callAjaxfunc(); //may have multiple ajax calls in this function
someWait(); // some code which waits until async calls complete
console.log('Pass2');

}

function callAjaxfunc() {
  //All ajax calls called here
  console.log('Pass1');

}

¿Qué he probado?

1 Jquery.when ()

Intenté usarlo ... funciona bien. Pero no de la forma que yo quiero. $.whenesperará, pero el código siguiente se $.when()ejecutará sin esperar. El código interno do callbacksolo se ejecuta después de llamadas ajax

2. setTimeOut () con una bandera global

Estaba tan seguro de que esto funcionaría. Intenté seguir.

GlobalFlag = false;

function someFunc()     
    callAjaxfunc(); //may have multiple ajax calls in this function
    setTimeOut(waitFunc, 100); // some  which waits until async calls complete
    console.log('Pass2');
}

function callAjaxfunc() {
    //All ajax calls called here
    onAjaxSuccess: function() {
        GlobalFlag = true;
    };
    console.log('Pass1');    
}

function waitFunc() {
    if (!GlobalFlag) {
        setTimeOut(waitFunc, 100);
    }
}​

Todavía no puedo obtener el resultado deseado. ¿Estoy haciendo algo mal aquí? ¿Esta no es la manera?

El resultado que quería debería venir así

Pass1
Pass2

No puede hacer ningún violín ya que necesita llamadas AJAX

EDITAR : Como muchos sugirieron devoluciones de llamada ... sé sobre ellos ... pero aún así el código al lado somewait()se ejecutará ... Quiero que el navegador deje de ejecutar el código al lado somewait()hasta la llamada ajax ... También puede ser una mala práctica pero vale la pena conocerlo y probarlo si es posible ...

6
  • Para su información, jsfiddle.net admite pruebas ajax. ¿No puedes mover el código después del someWaitinterior de las .thendevoluciones de llamada? 25/12/12 a las 14:22
  • 2
    Utilice la función de devolución de llamada de la llamada ajax 25/12/12 a las 14:22
  • Usar callbacks ( $.when) es la única forma razonable de hacer esto ... 25/12/12 a las 15:09
  • Sé acerca de las devoluciones de llamada ... esa es la forma básica ... pero aquí quiero detener el navegador para hacer cualquier cosa ... hasta que finalicen las llamadas Ajax. 25/12/12 a las 16:15
  • @ FabrícioMatté..cómo agregar llamadas ajax ?? ... 25/12/12 a las 16:19
61

Utilice devoluciones de llamada. Algo como esto debería funcionar según su código de muestra.

function someFunc() {

callAjaxfunc(function() {
    console.log('Pass2');
});

}

function callAjaxfunc(callback) {
    //All ajax calls called here
    onAjaxSuccess: function() {
        callback();
    };
    console.log('Pass1');    
}

Esto se imprimirá Pass1inmediatamente (asumiendo que la solicitud ajax tarda al menos unos microsegundos), luego se imprimirá Pass2cuando onAjaxSuccessse ejecute.

6
  • 8
    Sé acerca de las devoluciones de llamada ... esa es la forma básica ... pero aquí quiero detener el navegador para hacer cualquier cosa ... hasta que finalicen las llamadas Ajax ... 25/12/12 a las 16:14
  • 2
    @CodeJack, no creo que eso sea posible en javascript. ¿Qué es exactamente lo que quiere lograr al hacer eso, que no se puede hacer de esta manera? (es decir, mover el código a una devolución de llamada).
    Dogbert
    25/12/12 a las 19:25
  • 3
    la cosa es que estoy usando un marco propio ... hay una función de carga donde la página comienza a cargarse y antes de que se cargue la página necesito obtener datos y la única función que puedo anular es la función de carga ... 26/12/12 a las 8:15
  • ¿Así que cargue los datos antes de llamar al marco? Intentar hacer un bloque js es una mala idea. Es técnicamente posible usar solicitudes sincrónicas, pero es una idea terrible que nunca debería usarse. developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/…
    Ajax
    16 de ene. De 2017 a las 22:15
  • Puede haber situaciones en las que las devoluciones de llamada sean inapropiadas, por ejemplo: webview.clearData({since: 0}, clearDataType, function(){ ... // recreate fresh webview });supondrá un acaparamiento de recursos (Chrome creará una nueva copia del almacenamiento local esperando hasta que la anterior se libere de las referencias de la devolución de llamada interna, lo que nunca sucederá.
    Vlad
    21/06/18 a las 16:46
20

¿Por qué no funcionó para ti Deferred Objects? A menos que haya entendido mal algo, esto puede funcionar para usted.

/* AJAX success handler */
var echo = function() {
    console.log('Pass1');
};

var pass = function() {
  $.when(
    /* AJAX requests */
    $.post("/echo/json/", { delay: 1 }, echo),
    $.post("/echo/json/", { delay: 2 }, echo),
    $.post("/echo/json/", { delay: 3 }, echo)
  ).then(function() {
    /* Run after all AJAX */
    console.log('Pass2');
  });
};​

Véalo aquí .


ACTUALIZAR

Según su entrada, parece que su alternativa más rápida es usar solicitudes sincrónicas. Puede establecer la propiedad asyncen falseen sus $.ajaxsolicitudes para que se bloqueen. Sin embargo, esto colgará su navegador hasta que finalice la solicitud.

Tenga en cuenta que no recomiendo esto y todavía considero que debe corregir su código en un flujo de trabajo basado en eventos para no depender de él.

12
  • Intenté usar 'when' ... pero la forma en que quiero es que el navegador deje de hacer nada hasta que se complete la llamada Ajax ... y básicamente este código es durante la carga ... 25/12/12 a las 16:17
  • @CodeJack, siento que le diga pero el navegador no debe esperar, usted debe esperar 25/12/12 a las 16:30
  • 1
    @CodeJack, si todavía quiere ir con él fijado asynca falselas llamadas AJAX que desea realizar el bloqueo 25/12/12 a las 16:38
  • oh..there es propiedad al conjunto asyncde false... thanks..let que compruebe en that..Thanks .. 25/12/12 a las 16:46
  • @CodeJack, ¿funcionó mejor? 26/12/12 a las 14:24
8

Los programadores reales lo hacen con semáforos.

Tener una variable establecida en 0. Increméntelo antes de cada llamada AJAX. Disminuirlo en cada controlador de éxito y probar 0. Si es así, ya está.

8
  • 4
    semáforos es algo disponible en lenguajes de programación, no en JavaScript ... 25/12/12 a las 16:24
  • 2
    Los semáforos, como las secciones críticas, son técnicas que permiten compartir recursos de forma segura entre subprocesos / procesos. Creo que estás confundido con el término. Como @CodeJack dice que este tipo de objetos no están disponibles en Javascript, pero si así fuera, no serían aplicables en este caso.
    HMarioD
    25/12/12 a las 17:05
  • 2
    @HMarioD: ¿Estoy confundido? en.wikipedia.org/wiki/Asynchronous_semaphore : tenga en cuenta que todos los ejemplos están en JavaScript .
    Amadan
    26/12/12 a las 0:12
  • 3
    @CodeJack: Como menciona mi comentario anterior, los semáforos son absolutamente aplicables a JavaScript. El concepto que JavaScript no tiene es un bloqueo , debido a la ausencia de concurrencia. Los semáforos son contadores glorificados, a menudo utilizados junto con bloqueos (ya que en un entorno multiproceso los necesita absolutamente).
    Amadan
    26/12/12 a las 0:14
  • 1
    @HMarioD: Podría ser :) Sin embargo, combina dos viejos chistes ( uno dos ), fue divertido para mí.
    Amadan
    26/12/12 a las 15:26
0

Si necesita esperar hasta que se complete la llamada ajax, todo lo que necesita es hacer su llamada sincrónicamente.

6
  • 8
    Mala práctica en JS.
    Trevor
    25/12/12 a las 14:38
  • 3
    ¿Podría explicarme por qué hacer una llamada sincrónica es una mala práctica cuando lo que necesitamos es hacer la llamada sincrónica? Por favor.
    HMarioD
    25/12/12 a las 14:42
  • 4
    Bueno, especialmente en este caso de AJAX, congelará todo el navegador mientras intenta completar. JS se ejecuta en un bucle de eventos. No desea bloquear código no relacionado.
    Trevor
    25/12/12 a las 14:46
  • 4
    @Trevor en algunos casos es necesario detener todo hasta que se realice alguna acción o se alcance un tiempo de espera, la pregunta original de este post sugiere algún tipo de sincronismo entre llamadas. No conozco el panorama completo de este caso, pero sé que las "prácticas divinas" deben reconsiderarse en cada caso para obtener el mejor resultado. Existe normalización, pero algún tipo de desnormalización en algún momento es saludable. Somos libres de tomar nuestras propias decisiones. Lo siento mi pobre inglés y feliz navidad.
    HMarioD
    25/12/12 a las 15:17
  • @ Trevor ... como Mario sugirió, el problema con el mío es que estoy usando un marco (interno) ... y aquí en la carga, la llamada debería ir y el navegador debería esperar hasta que finalice la llamada Ajax. 25/12/12 a las 16:19