Pregunta ¿Cómo puedo obtener jQuery para realizar una solicitud Ajax síncrona, 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 regresar false para evitar que un artículo sea creado.

He agregado 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 artículo, 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 sincrónica utilizando jQuery o cualquier otra API en el navegador?


1050
2017-09-25 13:26


origen


Respuestas:


Desde el documentación jQuery: usted especifica el asincrónico opción para ser falso para obtener una solicitud síncrona de Ajax Luego, su devolución de llamada puede establecer algunos datos antes de que la función madre continúe.

Así es como se vería su código si cambiara según lo sugerido:

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
    });
}

1032
2017-09-25 13:30



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

jQuery.ajaxSetup({async:false});

Y luego realiza tus llamadas Ajax usando jQuery.get( ... );

Luego solo encenderlo nuevamente una vez

jQuery.ajaxSetup({async:true});

Supongo que funciona igual que lo sugerido por @Adam, pero podría ser útil para alguien que quiere reconfigurar su jQuery.get() o jQuery.post() a los más elaborados jQuery.ajax() sintaxis.


237
2018-04-12 21:45



Excelente solución! Cuando intenté implementarlo noté que si devolvía un valor en la cláusula de éxito, regresaba como indefinido. Tenía 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;
}

125
2018-04-07 13:30



Todas estas respuestas omiten el hecho de que realizar una llamada Ajax con async: false hará que el navegador se cuelgue hasta que se complete la solicitud de Ajax. El uso de una biblioteca de control de flujo resolverá este problema sin tener que colgar el navegador. Aquí hay un ejemplo con Frame.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();
}

82
2018-04-28 17:41



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


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

49
2018-04-25 15:34



Tenga en cuenta que si está haciendo una llamada Ajax entre dominios (mediante el uso de JSONP) - tú hipocresía hazlo sincrónicamente, el async bandera será ignorada por jQuery.

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

Para las llamadas JSONP, puede usar:

  1. Ajax: llame a su propio dominio y haga la llamada de dominio cruzado desde el servidor
  2. Cambie su código para trabajar asincrónicamente
  3. Use una biblioteca de "secuenciador de funciones" como Frame.js (esto responder)
  4. Bloquee la IU en lugar de bloquear la ejecución (esto responder) (mi forma favorita)

22
2018-05-10 06:28



Nota: No debe usar asincrónico debido a esto:

Comenzando con Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27), las solicitudes síncronas en el hilo principal han quedado obsoletas debido a los efectos negativos para la experiencia del usuario.

Chrome incluso advierte sobre esto en la consola:

La XMLHttpRequest sincrónica 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 quieres hacerlo de una manera que parezca sincronizada pero que no bloquee, debes utilizar async / await y probablemente también algún ajax basado en promesas como el nuevo Ha podido recuperar API

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

17
2017-12-13 12:55



Con async: false consigues un navegador bloqueado Para una solución sincrónica que no bloquea, puede usar lo siguiente:

ES6 / ECMAScript2015

Con ES6 puedes usar un generador y biblioteca co:

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 puedes 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
    })(); 
}

9
2017-08-20 19:52