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

StackOverflow https://stackoverflow.com/questions/133310

Frage

Ich habe ein JavaScript-Widget, das Standarderweiterungspunkte bereitstellt.Einer davon ist der beforecreate Funktion.Es sollte zurückkehren false um zu verhindern, dass ein Artikel erstellt wird.

Ich habe dieser Funktion mithilfe von jQuery einen Ajax-Aufruf hinzugefü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);
  });
}

Da ich jedoch verhindern möchte, dass mein Widget das Element erstellt, sollte ich zurückkehren false in der Mutterfunktion, nicht im Rückruf.Gibt es eine Möglichkeit, eine synchrone AJAX-Anfrage mit jQuery oder einer anderen browserinternen API auszuführen?

War es hilfreich?

Lösung

Von der jQuery Dokumentation : Geben Sie die asynchrone Option sein false eine synchrone Ajax-Anfrage zu bekommen. Dann wird Ihr Rückruf einige Daten vor Ihrer Mutter Funktion Erlös einstellen können.

Hier ist, was Ihr Code aussehen würde, wenn wie vorgeschlagen geändert:

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

Andere Tipps

können Sie die Ajax-Setup im synchronen Modus jQuery setzen durch den Aufruf

jQuery.ajaxSetup({async:false});

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

Drehen Dann ist es nur wieder einmal

jQuery.ajaxSetup({async:true});

Ich denke, es funktioniert auf die gleiche Sache wie von @ Adam vorgeschlagen, aber es könnte jemand hilfreich sein, die ihre jQuery.get() oder jQuery.post() auf die aufwändigere jQuery.ajax() Syntax neu konfigurieren möchte.

Ausgezeichnete Lösung! Ich bemerkte, als ich versuchte, es zu implementieren, dass, wenn ich einen Wert in der Erfolgsklausel zurückkehren, als undefiniert kam zurück. Ich hatte es in einer Variablen zu speichern und diese Variable zurück. Dies ist die Methode, die ich kam mit:

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

Alle diese Antworten vermissen den Punkt, dass ein Ajax-Aufruf mit Asynchron tun: false der Browser hängen verursacht, bis die Ajax-Anfrage abgeschlossen ist. eine Flusssteuerung Bibliothek wird dieses Problem lösen, ohne den Browser auflegt. Hier ist ein Beispiel mit 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();
}
function getURL(url){
    return $.ajax({
        type: "GET",
        url: url,
        cache: false,
        async: false
    }).responseText;
}


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

Beachten Sie, dass, wenn Sie tun, eine Cross-Domain Ajax-Aufruf (unter Verwendung von JSONP ) - Sie < strong> kann es nicht synchron zu tun, wird die async Flagge von jQuery ignoriert werden.

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

Für JSONP-Anrufe können Sie verwenden:

  1. Ajax-Aufruf zu Ihrer eigenen Domain - und tut die Cross-Domain-Call-Server-Seite
  2. Ändern Sie Ihren Code asynchron arbeiten
  3. Verwenden Sie eine "Funktion Sequenzer" Bibliothek wie Frame.js (diese beantworten )
  4. blockieren die Benutzeroberfläche stattdessen die Ausführung der Blockierung (diese beantworten ) (mein Favorit Weg)

Hinweis: Sie sollten nicht async: false aufgrund dieser Warnmeldungen verwenden:

  

Beginnend mit Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27), synchrone Anforderungen an den Hauptthread haben aufgrund der negativen Auswirkungen auf die User Experience veraltet.

Chrome sogar warnt darüber in der Konsole:

  

Synchrone XMLHttpRequest auf dem Hauptthread ist veraltet wegen seiner schädlichen Auswirkungen auf die Erfahrung des Endbenutzers. Weitere Hilfe überprüfen https://xhr.spec.whatwg.org/ .

Dies könnte brechen Ihrer Seite, wenn Sie so etwas wie dies tun, da es jeden Tag aufhören könnte zu arbeiten.

Wenn Sie wollen, dass es einen Weg zu tun, die immer noch wie fühlt, wenn es synchron, aber immer noch nicht blockieren, dann sollten Sie verwenden async / erwarten und wahrscheinlich auch einig Ajax, die auf Versprechungen wie die neuen API Fetch

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

Bearbeiten Chrom arbeitet an sync XHR in Seite Entlassungs Verbieten, wenn die Seite entfernt wird, navigiert oder geschlossen ist, indem der Benutzer. Dies beinhaltet beforeunload, Entladen, pagehide und visibilitychange.

, wenn dies Ihr Anwendungsfall dann könnten Sie einen Blick haben wollen? navigator.sendBeacon statt

Es ist auch möglich, dass die Seite mit entweder HTTP-Header-Sync-req zu deaktivieren oder das Attribut erlauben iframe

Mit async: false Sie holen Sie sich einen blockierten Browser. Für eine nicht blockierende Synchronlösung Sie folgende verwenden:

ES6 / ECMAScript2015

Mit ES6 können Sie einen Generator verwenden und die 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 verwenden 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
    })(); 
}

Ich habe die Antwort von Carcione verwendet und sie so geändert, dass JSON verwendet wird.

 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 das hinzugefügt Datentyp von 'JSON' und änderte das .responseText Zu AntwortJSON.

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

Das Back-End muss die Antwort im korrekten (wohlgeformten) JSON zurückgeben, andernfalls ist das zurückgegebene Objekt undefiniert.

Bei der Beantwortung der ursprünglichen Frage sind zwei Aspekte zu berücksichtigen.Eine besteht darin, Ajax anzuweisen, synchron auszuführen (durch Einstellung). asynchron:FALSCH) und der andere gibt die Antwort über die Return-Anweisung der aufrufenden Funktion zurück und nicht in eine Callback-Funktion.

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

Ich habe GET in POST geändert und hinzugefügt Daten:Post-Daten

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 dann funktioniert, wenn asynchron Ist FALSCH.Wenn Sie einstellen würden asynchron:WAHR das zurückgegebene Objekt jqxhr wäre zum Zeitpunkt der Rückkehr des AJAX-Aufrufs nicht gültig, sondern erst später, wenn der asynchrone Aufruf beendet ist, aber das ist viel zu spät, um das festzulegen Antwort Variable.

Dies ist Beispiel:

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

Erstens sollten wir verstehen, wenn wir $ verwenden Schnipsel und wenn wir verwenden $ .get / $. Post

Wenn wir geringe Kontrolle über die Ajax-Anforderung wie Request-Header-Einstellungen, Caching-Einstellungen, synchrone Einstellungen erfordern etc.then wir für $ .ajax gehen sollten.

$ get / $ post:... Wenn wir benötigen keine geringe Kontrolle über die Ajax request.Only einfach get / post die Daten an den Server Es ist eine Abkürzung von

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

und daher können wir nicht andere Funktionen nutzen (sync, Cache etc.) mit $ .get / $. Post.

Daher für niedrige Pegelsteuerung (sync, Cache, etc.) Über Ajax-Anforderung, wir sollten für $ gehen .ajax

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

Das ist meine einfache Implementierung für ASYNC-Anfragen mit jQuery. Ich hoffe, dass diese Hilfe jemand.

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

Da XMLHttpReponse Synchronbetrieb ist veraltet I mit folgenden Lösung kam, die XMLHttpRequest wickelt. Dies ermöglicht eine AJAX-Abfragen bestellt, während immer noch asycnronous ist in der Natur, die für den einmaligen Gebrauch CSRF-Token sehr nützlich ist.

Es ist auch transparent, so Bibliotheken wie jQuery nahtlos betrieben werden kann.

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

Das ist mein „ Thema “ Namespace:

var Thread = {
    sleep: function(ms) {
        var start = Date.now();

        while (true) {
            var clock = (Date.now() - start);
            if (clock >= ms) break;
        }

    }
};

Und das ist, wie ich es nennen:

var d1 = new Date();
console.log('start ' + d1.toLocaleTimeString());
Thread.sleep(10000);
var d2 = new Date();
console.log('end ' + d2.toLocaleTimeString());

Und wenn Blick auf die Konsole wir folgendes Ergebnis:

start 1:41:21 PM
end 1:41:31 PM
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top