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




jquery tooltip html (11)

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


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

Ich habe ein JavaScript-Widget, das Standard-Erweiterungspunkte bietet. Einer von ihnen ist die beforecreate Funktion. Es sollte false , um zu verhindern, dass ein Objekt 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, daher sollte ich in der mother-Funktion false , nicht im Callback. Gibt es eine Möglichkeit, eine synchronisierte Ajax-Anfrage mit jQuery oder einer anderen API durchzuführen?


Dies ist meine einfache Implementierung für ASYNC-Anfragen mit jQuery. Ich hoffe, dass dies jedem hilft.

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

Zuerst sollten wir verstehen, wenn wir $ .ajax verwenden und wenn wir $ .get / $. Post verwenden

Wenn wir eine Low-Level-Kontrolle über die Ajax-Anfrage benötigen, wie zum Beispiel Anforderungs-Header-Einstellungen, Cache-Einstellungen, synchrone Einstellungen usw., sollten wir uns für $ .ajax entscheiden.

$ .get / $. post: Wenn wir keine Low-Level-Kontrolle über die Ajax-Anfrage benötigen.Nur einfach Get / Post die Daten auf den Server. Es ist eine Abkürzung von

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

und daher können wir keine anderen Funktionen (Sync, Cache usw.) mit $ .get / $. post verwenden.

Daher sollten wir für die Low-Level-Kontrolle (Sync, Cache, etc.) über Ajax-Anfrage nach $ .ajax gehen

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

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. Weitere Hilfe erhalten Sie unter 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 der neuen Fetch API basiert

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

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

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

jQuery.ajaxSetup({async:false});

jQuery.get( ... ); dann Ihre Ajax-Aufrufe 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 hilfreich für jemanden sein, der seine jQuery.get() oder jQuery.post() zu der komplizierteren jQuery.ajax() Syntax umkonfigurieren jQuery.get() .


Wenn Sie einen domainübergreifenden Ajax-Aufruf durchführen (indem Sie JSONP ) - Sie können dies nicht synchron tun, 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 "Funktionssequenzer" -Bibliothek wie Frame.js (diese answer )
  4. Blockiere die Benutzeroberfläche, anstatt die Ausführung zu blockieren (diese answer ) (meine Lieblingsmethode)

Ich habe die Antwort von Carcione benutzt und sie für JSON modifiziert.

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

Ich habe den Datentyp von 'JSON' hinzugefügt und den .responseText zu responseJSON geändert.

Ich habe den Status auch mithilfe der statusText- Eigenschaft des zurückgegebenen Objekts abgerufen. Beachten Sie, dass dies der Status der Ajax-Antwort ist, nicht ob der JSON gültig ist.

Das Back-End muss die Antwort in korrektem (wohlgeformtem) JSON zurückgeben, andernfalls ist das zurückgegebene Objekt nicht definiert.

Bei der Beantwortung der ursprünglichen Frage müssen zwei Aspekte berücksichtigt werden. Einer sagt Ajax, synchron zu arbeiten (indem async: false gesetzt wird ), und der andere gibt die Antwort über die return-Anweisung der aufrufenden Funktion und nicht in eine Callback-Funktion zurück.

Ich habe es auch mit POST versucht und es hat funktioniert.

Ich änderte den GET zu POST und fügte Daten hinzu : 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;
}

Beachten Sie, dass der obige Code nur funktioniert, wenn async falsch ist . Wenn Sie async: true setzen würden, wäre das zurückgegebene Objekt jqxhr zum Zeitpunkt der Rückgabe des AJAX-Aufrufs nicht gültig, erst später, wenn der asynchrone Aufruf beendet ist, aber das ist viel zu spät, um die Antwortvariable zu setzen.


Aus der jQuery-Dokumentation : Sie geben die asynchrone Option als false an, um eine synchrone Ajax-Anforderung zu erhalten. 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
    });
}

Mit async: false bekommst du 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 und die Co-Bibliothek verwenden :

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

Dies ist ein Beispiel:

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






asynchronous