Frage Wie kann ich jQuery dazu bringen, eine synchrone anstelle einer asynchronen Ajax-Anfrage auszuführen?


Ich habe ein JavaScript-Widget, das Standard-Erweiterungspunkte bietet. Einer von ihnen ist der beforecreate Funktion. Es sollte zurückkehren false um zu verhindern, dass ein Artikel erstellt wird.

Ich habe mit jQuery einen Ajax-Aufruf in diese Funktion eingefügt:

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

Aber ich möchte verhindern, dass mein Widget das Element erstellt, also sollte ich zurückkehren false in der mother-Funktion, nicht im Callback. Gibt es eine Möglichkeit, eine synchrone AJAX-Anfrage mit jQuery oder einer anderen In-Browser-API auszuführen?


1050
2017-09-25 13:26


Ursprung


Antworten:


Von dem jQuery-Dokumentation: Sie spezifizieren die asynchron Option zu sein falsch um eine synchrone Ajax-Anfrage zu bekommen. Dann kann Ihr Callback einige Daten setzen, bevor Ihre Mutterfunktion fortschreitet.

So würde Ihr Code aussehen, wenn er wie vorgeschlagen geändert wird:

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



Sie können das jjQuery-Ajax-Setup im synchronen Modus durch Aufruf von aufrufen

jQuery.ajaxSetup({async:false});

Und dann führen Sie Ihre Ajax-Anrufe mit jQuery.get( ... );

Dann einfach einmal wieder einschalten

jQuery.ajaxSetup({async:true});

Ich denke, es funktioniert genauso wie von @Adam vorgeschlagen, aber es könnte für jemanden hilfreich sein, der es neu konfigurieren möchte jQuery.get() oder jQuery.post() zu den ausgefeilteren jQuery.ajax() Syntax.


237
2018-04-12 21:45



Ausgezeichnete Lösung! Ich bemerkte, als ich versuchte, es zu implementieren, dass, wenn ich einen Wert in der Erfolgsklausel zurückgab, es als undefined zurückkam. Ich musste es in einer Variablen speichern und diese Variable zurückgeben. Dies ist die Methode, die ich entwickelt habe:

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



Bei all diesen Antworten fehlt der Punkt, bei dem ein Ajax-Aufruf mit async: false dazu führt, dass der Browser hängen bleibt, bis die Ajax-Anforderung abgeschlossen ist. Die Verwendung einer Flusssteuerungsbibliothek löst dieses Problem, ohne den Browser aufzuhängen. Hier ist ein Beispiel mit Rahmen.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



Beachten Sie Folgendes: Wenn Sie einen domainübergreifenden Ajax-Aufruf durchführen (mithilfe von JSONP) - Sie kippen mach es synchron, das async Flag wird von jQuery ignoriert.

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

Für JSONP-Aufrufe könnten Sie verwenden:

  1. Ajax-Anruf zu Ihrer eigenen Domain - und tun Sie die Cross-Domain-Call-Server-Seite
  2. Ändern Sie Ihren Code, um asynchron zu arbeiten
  3. Verwenden Sie eine "Function Sequencer" -Bibliothek wie Frame.js (dies Antworten)
  4. Blockieren Sie die Benutzeroberfläche, statt die Ausführung zu blockieren Antworten) (mein Lieblingsweg)

22
2018-05-10 06:28



Hinweis: Sie sollten Async deshalb nicht verwenden:

Seit Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27) sind synchrone Anfragen im Hauptthread aufgrund der negativen Auswirkungen auf die Benutzererfahrung veraltet.

Chrome warnt sogar davor in der Konsole:

Synchrone XMLHttpRequest auf dem Hauptthread wird aufgrund seiner nachteiligen Auswirkungen auf die Erfahrung des Endbenutzers nicht mehr empfohlen. Für weitere Hilfe, überprüfen Sie https://xhr.spec.whatwg.org/.

Dies könnte Ihre Seite beschädigen, wenn Sie so etwas tun, da es jeden Tag aufhören könnte zu arbeiten.

Wenn du es so machen willst, dass es sich immer noch anfühlt, als ob es synchron ist, aber trotzdem nicht blockiere, dann solltest du async / awaid verwenden und wahrscheinlich auch ein Ajax, das auf Versprechen wie dem neuen basiert Holen 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



Mit async: false Sie bekommen einen blockierten Browser. Für eine nicht blockierende synchrone Lösung können Sie Folgendes verwenden:

ES6 / ECMAScript2015

Mit ES6 können Sie einen Generator & das verwenden Co-Bibliothek:

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

Mit ES7 können Sie nur asyc warten:

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