¿Cómo puedo hacer que jQuery realice una solicitud Ajax sincrónica, en lugar de asincrónica?

Tengo un widget de JavaScript que proporciona puntos de extensión estándar. Uno de ellos es el beforecreate función. Debería volver false para evitar que se cree un elemento.

Agregué una llamada Ajax a esta función usando jQuery:

beforecreate: function (node, targetNode, type, to) {
  jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value),

  function (result) {
    if (result.isOk == false) 
        alert(result.message);
  });
}

Pero quiero evitar que mi widget cree el elemento, así que debería regresar false en la función madre, no en la devolución de llamada. ¿Hay alguna forma de realizar una solicitud AJAX síncrona utilizando jQuery o cualquier otra API en el navegador?

preguntado el 25 de septiembre de 08 a las 11:09

La forma correcta de resolver eso sería reescribir las promesas de uso del punto de extensión de su widget. De esta manera le permitiría configurar fácilmente una acción asincrónica (como una solicitud ajax) como beforecreate. -

Propongo la función Sajak. ¿Tenemos una letra T? Sí vanna, dame 3 T's. -

@Kos da en el clavo. No se requiere sincronizar XHR aquí -

Si la gente me pide un consejo al iniciar javascript, digo: adopte el carácter asincrónico de javascript, no intente luchar contra eso. -

Esta pregunta es como preguntar "¿cómo guardo mis contraseñas de usuario en texto sin formato?" Seguro que hay una respuesta, pero no la hagas. -

14 Respuestas

Desde el documentación de jQuery: especificas el asincrónico opción de ser false para obtener una solicitud Ajax sincrónica. Luego, su devolución de llamada puede establecer algunos datos antes de que proceda su función madre.

Así es como se vería su código si se cambiara como se sugiere:

beforecreate: function (node, targetNode, type, to) {
    jQuery.ajax({
        url: 'http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value),
        success: function (result) {
            if (result.isOk == false) alert(result.message);
        },
        async: false
    });
}

respondido 16 nov., 20:08

Exactamente, es imposible usar get (), post (), load () para llamadas sincrónicas. Solo ajax () tiene el parámetro "async", que se puede establecer en "false". - SLA80

@ SLA80 No. Desde jQuery 1.1: stackoverflow.com/questions/6849686/… - StuperUsuario

@qualidafial mi comentario está dirigido al comentario incorrecto de SLA80; es posible usar get (), post (), load () para llamadas sincrónicas. - StuperUsuario

async false ya no es compatible con jQuery> = 1.8. Consulte api.jquery.com/jQuery.ajax - ken

@conocer async: false todavía es compatible con jQuery> = 1.8. La capacidad de usar async: false con jqXHR ($.Deferred) es lo que quedó en desuso. En otras palabras, uno debe usar las opciones de devolución de llamada de éxito / error / completo más nuevas, en lugar de los métodos heredados, por ejemplo, jqXHR.done(). - Ben Johnson

Puede poner la configuración Ajax de jQuery en modo síncrono llamando

jQuery.ajaxSetup({async:false});

Y luego realice sus llamadas Ajax usando jQuery.get( ... );

Luego, enciéndelo de nuevo una vez

jQuery.ajaxSetup({async:true});

Supongo que funciona igual que lo sugerido por @Adam, pero podría ser útil para alguien que quiera reconfigurar su jQuery.get() or jQuery.post() a los mas elaborados jQuery.ajax() sintaxis.

respondido 30 mar '18, 22:03

Esta es una muy mala idea, ¿por qué la establecería a nivel global? ¿Y luego se verá obligado a desarmarlo después? - Juan mendes

Al menos, esta es la mejor mala idea. en lugar de decir: "NO HAY MANERA EXCEPTO $.ajax()".;) - Rzassar

Excelente solucion! Cuando intenté implementarlo, noté que si devolvía un valor en la cláusula de éxito, volvía como indefinido. Tuve que almacenarlo en una variable y devolver esa variable. Este es el método que se me ocurrió:

function getWhatever() {
  // strUrl is whatever URL you need to call
  var strUrl = "", strReturn = "";

  jQuery.ajax({
    url: strUrl,
    success: function(html) {
      strReturn = html;
    },
    async:false
  });

  return strReturn;
}

respondido 30 mar '18, 22:03

Eso es porque estaba devolviendo un valor de la devolución de llamada, no de getWhatever. Así volviste nada es decir, undefined a partir de su getWhatever. - Carreras de ligereza en órbita

esto es absolutamente incorrecto. No puede estar seguro de que una llamada asincrónica haya finalizado al devolver 'strReturn'. - Tomas Fritz

Esta es una llamada sincrónica (async: false). - James en Indy

Todas estas respuestas pierden el punto de que hacer una llamada Ajax con async: false hará que el navegador se cuelgue hasta que se complete la solicitud Ajax. El uso de una biblioteca de control de flujo resolverá este problema sin colgar el navegador. Aquí hay un ejemplo con Marco.js:

beforecreate: function(node,targetNode,type,to) {

    Frame(function(next)){

        jQuery.get('http://example.com/catalog/create/', next);
    });

    Frame(function(next, response)){

        alert(response);
        next();
    });

    Frame.init();
}

respondido 21 nov., 15:12

Las llamadas sincrónicas son útiles si desea armar un arnés de prueba rápido para un back-end REST y prefiere la simplicidad al infierno de devolución de llamada. - Distorsionar

function getURL(url){
    return $.ajax({
        type: "GET",
        url: url,
        cache: false,
        async: false
    }).responseText;
}


//example use
var msg=getURL("message.php");
alert(msg);

Respondido 25 Abr '12, 16:04

Sin embargo, tenga en cuenta que es posible que obtenga esto: "XMLHttpRequest síncrono en el hilo principal está en desuso debido a sus efectos perjudiciales para la experiencia del usuario final". - Hari

@Hari ¿Cuál es la forma de realizar una llamada ajax sincrónica usando jQuery sin usar el hilo principal? - José Nobile

No veo que esta respuesta tenga nada que ofrecer, es solo la respuesta aceptada envuelta en una función y respondida cuatro años después. Es malo aconsejar a la gente que haga C + P, porque la función no indica lo que hace. "Entonces getURL vs get ? ¿Por qué se cuelga mi navegador? ", etc. - Moopet

Nota: no deberías usar async: false debido a estos mensajes de advertencia:

A partir de Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27), las solicitudes sincrónicas en el hilo principal han quedado obsoletas debido a los efectos negativos en la experiencia del usuario.

Chrome incluso advierte sobre esto en la consola:

XMLHttpRequest sincrónico en el hilo principal está en desuso debido a sus efectos perjudiciales para la experiencia del usuario final. Para obtener más ayuda, consulte https://xhr.spec.whatwg.org/.

Esto podría romper su página si está haciendo algo como esto, ya que podría dejar de funcionar cualquier día.

Si desea hacerlo de una manera que todavía se siente como si fuera sincrónico pero aún no se bloquea, entonces debería usar async / await y probablemente también algún ajax que se base en promesas como la nueva Ha podido recuperar API

async function foo() {
  var res = await fetch(url)
  console.log(res.ok)
  var json = await res.json()
  console.log(json)
}

Editar Chrome está trabajando en No permitir la sincronización de XHR en el rechazo de la página cuando el usuario está navegando o cerrando la página. Esto implica antes de descargar, descargar, ocultar páginas y cambiar de visibilidad.

si este es su caso de uso, es posible que desee echar un vistazo a navigator.sendBeacon

También es posible que la página deshabilite la solicitud de sincronización con los encabezados http o el atributo allow de iframe.

Respondido 19 Feb 19, 13:02

Tenga en cuenta que debe envolver su await fetch(url) llamar a un try... catch bloquear para detectar cualquier error asincrónico. - inostia

la función foo se ha convertido en una promesa con solo usar la palabra async al principio, para que pudieras hacer foo().catch(...) para atraparlo también - Sin fin

Chrome ya no permitió ajax asíncrono dentro de la página beforeunload pero luego revirtió el cambio después de un comentario negativo bugs.chromium.org/p/chromium/issues/detail?id=952452 - Alex

Tenga en cuenta que si está haciendo una llamada Ajax entre dominios (utilizando JSONP) - usted no puedes hacerlo sincrónicamente, el async jQuery ignorará la bandera.

$.ajax({
    url: "testserver.php",
    dataType: 'jsonp', // jsonp
    async: false //IGNORED!!
});

Para llamadas JSONP, puede usar:

  1. Llame Ajax a su propio dominio y haga la llamada entre dominios del lado del servidor
  2. Cambie su código para que funcione de forma asincrónica
  3. Utilice una biblioteca de "secuenciador de funciones" como Frame.js (este https://www.youtube.com/watch?v=xB-eutXNUMXJtA&feature=youtu.be)
  4. Bloquear la interfaz de usuario en lugar de bloquear la ejecución (esto https://www.youtube.com/watch?v=xB-eutXNUMXJtA&feature=youtu.be) (mi forma favorita)

Respondido el 30 de junio de 17 a las 08:06

Usé la respuesta dada por Carcione y la modifiqué para usar JSON.

 function getUrlJsonSync(url){

    var jqxhr = $.ajax({
        type: "GET",
        url: url,
        dataType: 'json',
        cache: false,
        async: false
    });

    // 'async' has to be 'false' for this to work
    var response = {valid: jqxhr.statusText,  data: jqxhr.responseJSON};

    return response;
}    

function testGetUrlJsonSync()
{
    var reply = getUrlJsonSync("myurl");

    if (reply.valid == 'OK')
    {
        console.dir(reply.data);
    }
    else
    {
        alert('not valid');
    }    
}

Agregué el tipo de datos of 'JSON' y cambió el .responseText a respuestaJSON.

También recuperé el estado usando el estadoTexto propiedad del objeto devuelto. Tenga en cuenta que este es el estado de la respuesta Ajax, no si el JSON es válido.

El back-end tiene que devolver la respuesta en JSON correcto (bien formado), de lo contrario, el objeto devuelto no estará definido.

Hay dos aspectos a considerar al responder a la pregunta original. Uno le está diciendo a Ajax que actúe sincrónicamente (estableciendo async: falso) y el otro devuelve la respuesta a través de la declaración de retorno de la función de llamada, en lugar de una función de devolución de llamada.

También lo probé con POST y funcionó.

Cambié GET a POST y agregué datos: postdata

function postUrlJsonSync(url, postdata){

    var jqxhr = $.ajax({
        type: "POST",
        url: url,
        data: postdata,
        dataType: 'json',
        cache: false,
        async: false
    });

    // 'async' has to be 'false' for this to work
    var response = {valid: jqxhr.statusText,  data: jqxhr.responseJSON};

    return response;
}

Tenga en cuenta que el código anterior solo funciona en el caso en que Asincrónico is false. Si tuvieras que establecer async: verdadero el objeto devuelto jqxhr no sería válido en el momento en que regresa la llamada AJAX, solo más tarde cuando la llamada asincrónica haya finalizado, pero es demasiado tarde para establecer el respuesta variable.

respondido 30 mar '18, 22:03

Con async: false obtienes un navegador bloqueado. Para una solución sincrónica sin bloqueo, puede utilizar lo siguiente:

ES6 / ECMAScript2015

Con ES6 puede utilizar un generador y el co biblioteca:

beforecreate: function (node, targetNode, type, to) {
    co(function*(){  
        let result = yield jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value));
        //Just use the result here
    });
}

ES7

Con ES7 puede usar asyc await:

beforecreate: function (node, targetNode, type, to) {
    (async function(){
        let result = await jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value));
        //Just use the result here
    })(); 
}

Respondido 20 ago 16, 20:08

Fíjate que puedes pasar async function antes de crear beforecreate: async function(.... y elimine la función asíncrona autoinvocada - daniel kron

Este es un ejemplo:

$.ajax({
  url: "test.html",
  async: false
}).done(function(data) {
   // Todo something..
}).fail(function(xhr)  {
   // Todo something..
});

Respondido 16 ago 14, 14:08

¿Cuál es el punto de usar async false con una solución basada en promesas. Esto solo bloquea el navegador sin ningún beneficio. - Codificación ido

@GoneCoding hay situaciones en las que queremos ejecutar código en secuencia exacta, en esa situación podemos usar async false - Nikki

@Nikki: Eso es absolutamente no la forma de ejecutarlos secuencialmente. Utilice promesas asincrónicas (que ajax las llamadas ya regresan) y .then() or done() (como ya muestra). Bloquear el navegador es una experiencia de usuario muy mala. Como dije tener async: false en este ejemplo es una completa pérdida de tiempo. - Codificación ido

En primer lugar, debemos entender cuándo usamos $ .ajax y cuándo usamos $ .get / $. Post

Cuando requerimos un control de bajo nivel sobre la solicitud ajax, como la configuración del encabezado de la solicitud, la configuración del almacenamiento en caché, la configuración síncrona, etc., entonces deberíamos optar por $ .ajax.

$ .get / $. post: Cuando no requerimos un control de bajo nivel sobre la solicitud ajax. Solo es simple obtener / publicar los datos en el servidor.Es una abreviatura de

$.ajax({
  url: url,
  data: data,
  success: success,
  dataType: dataType
});

y por lo tanto no podemos usar otras funciones (sincronización, caché, etc.) con $ .get / $. post.

Por lo tanto, para el control de bajo nivel (sincronización, caché, etc.) sobre la solicitud ajax, deberíamos optar por $ .ajax

 $.ajax({
     type: 'GET',
      url: url,
      data: data,
      success: success,
      dataType: dataType,
      async:false
    });

Respondido 03 Oct 17, 10:10

esta es mi implementación simple para solicitudes ASYNC con jQuery. Espero que esto ayude a cualquiera.

var queueUrlsForRemove = [
    'http://dev-myurl.com/image/1', 
    'http://dev-myurl.com/image/2',
    'http://dev-myurl.com/image/3',
];

var queueImagesDelete = function(){

    deleteImage( queueUrlsForRemove.splice(0,1), function(){
        if (queueUrlsForRemove.length > 0) {
            queueImagesDelete();
        }
    });

}

var deleteImage = function(url, callback) {
    $.ajax({
        url: url,
        method: 'DELETE'
    }).done(function(response){
        typeof(callback) == 'function' ? callback(response) : null;
    });
}

queueImagesDelete();

Respondido 15 Feb 18, 19:02

Gracias XMLHttpReponse La operación síncrona está en desuso. Se me ocurrió la siguiente solución que envuelve XMLHttpRequest. Esto permite consultas AJAX ordenadas sin dejar de ser de naturaleza asíncrona, lo cual es muy útil para tokens CSRF de un solo uso.

También es transparente, por lo que las bibliotecas como jQuery funcionarán sin problemas.

/* wrap XMLHttpRequest for synchronous operation */
var XHRQueue = [];
var _XMLHttpRequest = XMLHttpRequest;
XMLHttpRequest = function()
{
  var xhr   = new _XMLHttpRequest();
  var _send = xhr.send;

  xhr.send = function()
  {
    /* queue the request, and if it's the first, process it */
    XHRQueue.push([this, arguments]);
    if (XHRQueue.length == 1)
      this.processQueue();
  };

  xhr.processQueue = function()
  {
    var call = XHRQueue[0];
    var xhr  = call[0];
    var args = call[1];

    /* you could also set a CSRF token header here */

    /* send the request */
    _send.apply(xhr, args);
  };

  xhr.addEventListener('load', function(e)
  {
    /* you could also retrieve a CSRF token header here */

    /* remove the completed request and if there is more, trigger the next */
    XHRQueue.shift();
    if (XHRQueue.length)
      this.processQueue();
  });

  return xhr;
};

Respondido 29 Abr '18, 14:04

Dado que la pregunta original era sobre jQuery.get, vale la pena mencionar aquí que (como se mencionó aquí) uno podría utilizan el async: false en un parche de $.get() pero idealmente evitar es asincrónico XMLHTTPRequest está en desuso (y el navegador puede dar una advertencia):

$.get({
  url: url,// mandatory
  data: data,
  success: success,
  dataType: dataType,
  async:false // to make it synchronous
});

Respondido el 11 de enero de 20 a las 17:01

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.