javascript - récupérer - script ajax




Comment puis-je faire en sorte que jQuery effectue une requête Ajax synchrone plutôt qu'asynchrone? (9)

J'ai un widget JavaScript qui fournit des points d'extension standard. L'un d'eux est la fonction beforecreate . Il devrait renvoyer false pour empêcher la création d'un élément.

J'ai ajouté un appel Ajax dans cette fonction en utilisant 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);
  });
}

Mais je veux empêcher mon widget de créer l'élément, donc je devrais retourner false dans la fonction mère, pas dans le rappel. Existe-t-il un moyen d'effectuer une requête Ajax synchronisée à l'aide de jQuery ou de toute autre API?


Avec async: false vous obtenez un navigateur bloqué. Pour une solution synchrone non bloquante, vous pouvez utiliser ce qui suit:

ES6 / ECMAScript2015

Avec ES6 vous pouvez utiliser un générateur et la bibliothèque de 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

Avec ES7, vous pouvez simplement utiliser 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
    })(); 
}

C'est ma mise en œuvre simple pour les requêtes ASYNC avec jQuery. J'espère que cela aide quelqu'un.

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

Dans la documentation de jQuery : vous spécifiez l'option asynchrone à false pour obtenir une requête Ajax synchrone. Ensuite, votre rappel peut définir certaines données avant que votre fonction mère ne se poursuive.

Voici à quoi ressemblerait votre code s'il était modifié comme suggéré:

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

Excellente solution! J'ai remarqué quand j'ai essayé de l'implémenter que si je retournais une valeur dans la clause de succès, elle revenait indéfinie. Je devais le stocker dans une variable et retourner cette variable. C'est la méthode que j'ai inventée:

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

J'ai utilisé la réponse donnée par Carcione et l'ai modifiée pour utiliser 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');
    }    
}

J'ai ajouté le dataType de 'JSON' et changé le .responseText en responseJSON .

J'ai également récupéré le statut en utilisant la propriété statusText de l'objet retourné. Notez que c'est le statut de la réponse Ajax, pas si le JSON est valide.

Le back-end doit retourner la réponse dans le JSON correct (bien formé), sinon l'objet retourné sera indéfini.

Il y a deux aspects à considérer en répondant à la question originale. L'une dit à Ajax de fonctionner de manière synchrone (en définissant async: false ) et l'autre renvoie la réponse via l'instruction return de la fonction appelante, plutôt que dans une fonction de rappel.

J'ai aussi essayé avec POST et cela a fonctionné.

J'ai changé le GET en POST et ajouté des données: 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;
}

Notez que le code ci-dessus ne fonctionne que dans le cas où async est faux . Si vous définissiez async: true, l'objet renvoyé jqxhr ne serait pas valide au moment où l'appel AJAX est renvoyé, mais seulement plus tard lorsque l'appel asynchrone sera terminé, mais il est beaucoup trop tard pour définir la variable de réponse .


Note: Vous ne devriez pas utiliser async à cause de ceci:

À partir de Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27), les requêtes synchrones sur le thread principal ont été abandonnées en raison des effets négatifs sur l'expérience utilisateur.

Chrome avertit même à ce sujet dans la console:

XMLHttpRequest synchrone sur le thread principal est obsolète en raison de ses effets préjudiciables à l'expérience de l'utilisateur final. Pour plus d'aide, consultez https://xhr.spec.whatwg.org/ .

Cela pourrait casser votre page si vous faites quelque chose comme ça, car il pourrait cesser de fonctionner n'importe quel jour.

Si vous voulez le faire de manière à ce qu'il soit toujours synchrone mais ne bloque pas, utilisez async / await et probablement aussi ajax basé sur des promesses comme la nouvelle Fetch API

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

Toutes ces réponses manquent le point qu'effectuer un appel Ajax avec async: false provoquera le blocage du navigateur jusqu'à la fin de la requête Ajax. L'utilisation d'une bibliothèque de contrôle de flux résoudra ce problème sans raccrocher le navigateur. Voici un exemple avec 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();
}

Vous pouvez mettre la configuration Ajax de jQuery en mode synchrone en appelant

jQuery.ajaxSetup({async:false});

Et puis effectuez vos appels Ajax en utilisant jQuery.get( ... );

Ensuite, il suffit de le rallumer une fois

jQuery.ajaxSetup({async:true});

Je suppose que cela fonctionne exactement comme suggéré par @Adam, mais cela peut être utile à quelqu'un qui veut reconfigurer jQuery.get() ou jQuery.post() à la syntaxe plus élaborée jQuery.ajax() .


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


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






asynchronous