jquery - valeur de retour en utilisant le résultat ajax en cas de succès


95

J'ai un petit problème avec la fonction jquery $ .ajax ().

J'ai un formulaire où chaque clic sur le bouton radio ou sélection dans le menu déroulant crée une variable de session avec la valeur sélectionnée.

Maintenant - j'ai l'un des menus déroulants qui ont 4 options - le premier (avec l'étiquette Aucun) a une valeur = "" les autres ont leurs identifiants.

Ce que je veux, c'est que l'option Aucun (avec une valeur vide) pour supprimer la session et l'autre pour en créer une, mais seulement si la session avec ce nom de sélection spécifique n'existe pas déjà - car toutes les autres options ont le même montant qui lui est attribué - il indique simplement lequel a été sélectionné.

Je ne sais pas si cela a du sens - mais jetez un œil au code - peut-être que cela le rendra plus clair:

$("#add_ons select").change(function() {
        // get current price of the addons
        var order_price_addon = $(".order_price_addon").text();
        // get price of the clicked radio button from the rel attribute
        var add = $(this).children('option').attr('label');
        var name = $(this).attr('name');
        var val = $(this).val();


        if(val == "") {
            var price = parseInt(order_price_addon) - parseInt(add);
            removeSession(name);
        } else {
            if(isSession(name) == 0) {
                var price = parseInt(order_price_addon) + parseInt(add);
            }   
            setSession(name, val);              
        }

        $(".order_price_addon").html(price);    
        setSession('order_price_addon', price);         
        updateTotal();
});

donc - tout d'abord, lorsque le menu de sélection #add_ons déclenche "changement", nous obtenons des valeurs de quelques éléments pour les calculs.

nous obtenons l'attribut label de l'option à partir de notre sélection qui stocke la valeur à ajouter au total, le nom de la session de sélection pour créer avec ce nom et cette valeur pour vérifier plus tard laquelle a été sélectionnée.

maintenant - nous vérifions si val == "" (qui indiquerait que l'option Aucun a été sélectionné) et nous déduisons le montant du total ainsi que supprimons la session avec le nom de la sélection.

Après c'est là que le problème commence - instruction else.

Sinon - nous voulons vérifier si la fonction isSession () avec le nom de notre sélecteur renvoie 0 ou 1 - si elle renvoie 0, nous ajoutons au total la valeur stockée dans l'attribut label, mais si elle renvoie 1 - cela suggérerait cette session existe déjà - alors nous ne modifions la valeur de cette session qu'en la recréant - mais le montant n'y est pas ajouté.

Maintenant, la fonction isSession ressemble à ceci:

function isSession(selector) {
    $.ajax({
        type: "POST",
        url: '/order.html',
        data: ({ issession : 1, selector: selector }),
        dataType: "html",
        success: function(data) {
            return data;
        },
        error: function() {
            alert('Error occured');
        }
    });
}

Maintenant - le problème est - que je ne sais pas si l'utilisation de "return" retournera le résultat de la fonction - car cela ne semble pas fonctionner - cependant, si je mets les "données" dans le succès: section dans le alert - il semble renvoyer la bonne valeur.

Est-ce que quelqu'un sait comment renvoyer la valeur de la fonction, puis la comparer dans l'instruction suivante?


Merci les gars - je l'ai essayé de la manière suivante:

function isSession(selector) {
    $.ajax({
        type: "POST",
        url: '/order.html',
        data: ({ issession : 1, selector: selector }),
        dataType: "html",
        success: function(data) {
            updateResult(data);
        },
        error: function() {
            alert('Error occured');
        }
    });
}

puis la fonction updateResult ():

function updateResult (données) {résultat = données; }

result - est la variable globale - que j'essaye alors de lire:

$("#add_ons select").change(function() {
        // get current price of the addons
        var order_price_addon = $(".order_price_addon").text();
        // get price of the clicked radio button from the rel attribute
        var add = $(this).children('option').attr('label');
        var name = $(this).attr('name');
        var val = $(this).val();


        if(val == "") {
            var price = parseInt(order_price_addon) - parseInt(add);
            removeSession(name);
        } else {
            isSession(name);
            if(result == 0) {
                var price = parseInt(order_price_addon) + parseInt(add);
            }   
            setSession(name, val);              
        }

        $(".order_price_addon").html(price);    
        setSession('order_price_addon', price);         
        updateTotal();
    });

mais pour une raison quelconque - ça ne marche pas - une idée?



Cela peut aider à résoudre ce problème: stackoverflow.com/questions/14220321/…
mirzaei.sajad

Réponses:


114

Le problème est que vous ne pouvez pas renvoyer une valeur à partir d'un appel asynchrone, comme une requête AJAX, et vous attendre à ce que cela fonctionne.

La raison en est que le code en attente de la réponse a déjà été exécuté au moment où la réponse est reçue.

La solution à ce problème consiste à exécuter le code nécessaire dans le success:rappel. De cette façon, il accède au dataseul lorsqu'il est disponible.

function isSession(selector) {
    $.ajax({
        type: "POST",
        url: '/order.html',
        data: ({ issession : 1, selector: selector }),
        dataType: "html",
        success: function(data) {
            // Run the code here that needs
            //    to access the data returned
            return data;
        },
        error: function() {
            alert('Error occured');
        }
    });
}

Une autre possibilité (qui est effectivement la même chose) est d'appeler une fonction à l'intérieur de votre success:callback qui transmet les données lorsqu'elles sont disponibles.

function isSession(selector) {
    $.ajax({
        type: "POST",
        url: '/order.html',
        data: ({ issession : 1, selector: selector }),
        dataType: "html",
        success: function(data) {
                // Call this function on success
            someFunction( data );
            return data;
        },
        error: function() {
            alert('Error occured');
        }
    });
}

function someFunction( data ) {
    // Do something with your data
}

11
Vous POUVEZ renvoyer une valeur à partir d'une requête AJAX, mais ce n'est que si vous la rendez non asynchrone (définissez l'option async: false). Dans certains cas, un appel asynchrone n'est pas obligatoire. Plus d'informations sur jquery.ajax () doc api.jquery.com/jQuery.ajax , not thatAs of jQuery 1.8, the use of async: false with jqXHR ($.Deferred) is deprecated;
Adrien Be

48
"Non-asynchrone" peut bien sûr également être appelé "synchrone";)
Charles Wood

dans les deux méthodes que vous avez suggérées; c'est à dire. exécutez la fonction avec succès, puis vous devez écrire plusieurs ajax pour différents scénarios. cela n'aidera pas à créer un wrapper ajax global, un moteur.
wpcoder

Il semble, async: false est maintenant obsolète et tout le traitement doit être effectué dans les fonctions de rappel.
Puneet Lamba

31

Il existe de nombreuses façons d'obtenir une réponse jQuery AJAX. Je partage avec vous deux approches communes:

Première:

utilisez async = false et dans la fonction retournez objet ajax et plus tard, obtenez la réponse ajax-object.responseText

/**
 * jQuery ajax method with async = false, to return response
 * @param  {mix}  selector - your selector
 * @return {mix}           - your ajax response/error
 */
function isSession(selector) {
    return $.ajax({
        type: "POST",
        url: '/order.html',
        data: {
            issession: 1,
            selector: selector
        },
        dataType: "html",
        async: !1,
        error: function() {
            alert("Error occured")
        }
    });
}
// global param
var selector = !0;
// get return ajax object
var ajaxObj = isSession(selector);
// store ajax response in var
var ajaxResponse = ajaxObj.responseText;
// check ajax response
console.log(ajaxResponse);
// your ajax callback function for success
ajaxObj.success(function(response) {
    alert(response);
});

Seconde:

utilisez la méthode $ .extend et créez une nouvelle fonction comme ajax

/**
 * xResponse function
 *
 * xResponse method is made to return jQuery ajax response
 * 
 * @param  {string} url   [your url or file]
 * @param  {object} your ajax param
 * @return {mix}       [ajax response]
 */
$.extend({
    xResponse: function(url, data) {
        // local var
        var theResponse = null;
        // jQuery ajax
        $.ajax({
            url: url,
            type: 'POST',
            data: data,
            dataType: "html",
            async: false,
            success: function(respText) {
                theResponse = respText;
            }
        });
        // Return the response text
        return theResponse;
    }
});

// set ajax response in var
var xData = $.xResponse('temp.html', {issession: 1,selector: true});

// see response in console
console.log(xData);

vous pouvez le faire aussi grand que vous le souhaitez ...


Bonne idée mais ajaxObj['responseText']n'existe pas lorsque vous définissezvar ajaxResponse
mu3

Parfait!! votre première solution m'a sauvé
Kallel Omar

la deuxième méthode est 100% A OK! ;)
Schalk Keun

7
Depuis jQuery 1.8, l'utilisation de async: false est obsolète!
gatteo

10

J'ai vu les réponses ici et bien que utiles, elles n'étaient pas exactement ce que je voulais car j'ai dû modifier une grande partie de mon code.

Ce qui a fonctionné pour moi, c'est de faire quelque chose comme ça:

function isSession(selector) {
    //line added for the var that will have the result
    var result = false;
    $.ajax({
        type: "POST",
        url: '/order.html',
        data: ({ issession : 1, selector: selector }),
        dataType: "html",
        //line added to get ajax response in sync
        async: false,
        success: function(data) {
            //line added to save ajax response in var result
            result = data;
        },
        error: function() {
            alert('Error occured');
        }
    });
    //line added to return ajax response
    return result;
}

L'espoir aide quelqu'un

anakin


4
En fait, vous venez de désactiver l'asynchronisation
Weijing Jay Lin

4

Bien que toutes les approches concernant l'utilisation de async: false ne soient pas bonnes en raison de sa dépréciation et ont bloqué la page jusqu'à ce que la demande revienne. Voici donc 2 façons de le faire:

1er: Renvoie toute la réponse ajax dans une fonction, puis utilise la donefonction pour capturer la réponse lorsque la demande est terminée. (RECOMMANDÉ, LA MEILLEURE MANIÈRE)

function getAjax(url, data){
    return $.ajax({
        type: 'POST',
        url : url,              
        data: data,
        dataType: 'JSON',
        //async: true,  //NOT NEEDED
        success: function(response) {
            //Data = response;
        }
    });
 }

APPELEZ LE CI-DESSUS COMME SO:

getAjax(youUrl, yourData).done(function(response){
    console.log(response);
});

POUR PLUSIEURS APPELS AJAX, UTILISEZ $.when:

$.when( getAjax(youUrl, yourData), getAjax2(yourUrl2, yourData2) ).done(function(response){
    console.log(response);
});

2ème: Stockez la réponse dans un cookie, puis en dehors de l'appel ajax, obtenez cette valeur de cookie. (NON RECOMMANDÉ)

        $.ajax({
            type: 'POST',
            url : url,              
            data: data,
            //async: false,    // No need to use this
            success: function(response) {
                Cookies.set(name, response);
            }
        });

        // Outside of the ajax call
        var response = Cookies.get(name);

REMARQUE: Dans l'exemple ci-dessus, la jquery cookiesbibliothèque est utilisée. Elle est assez légère et fonctionne aussi rapidement. Voici le lien https://github.com/js-cookie/js-cookie


3

Ajoutez async: falseà votre liste d'attributs. Cela force le thread javascript à attendre que la valeur de retour soit récupérée avant de continuer. Évidemment, vous ne voudriez pas faire cela dans toutes les circonstances, mais si une valeur est nécessaire avant de continuer, cela le fera.


3
Vous ne devriez jamais vous fixer async: false. Cela bloque tout sur la page pendant la durée de la récupération. Vous savez ce que signifie le A dans AJAX: Asynchrone. La bonne réponse serait que OP doit utiliser success()correctement le rappel.
nietonfir

2
J'ai reconnu le fait que tout doit attendre. Dans certaines circonstances, la fonction appelante peut avoir besoin d'une valeur retournée, telle que l'ajout d'un nouvel enregistrement et le retour d'un identifiant d'enregistrement. Une fois que vous connaissez les règles, vous savez quand elles peuvent être enfreintes. Ne jamais dire jamais. Voici quelqu'un d'autre qui est d'accord. ( stackoverflow.com/questions/3880361/… )
Hoodlum

1
@CharlesWood Uniquement pour ceux qui ne peuvent pas saisir la nature asynchrone de l'ajax.
nietonfir le

1
@nietonfir: si vous ne deviez jamais utiliser, async: falsepourquoi jQuery aurait-il implémenté cette option? si je ne charge pas de grandes quantités de données sur la page et que je gère simplement un événement utilisateur, il est normal que cela bloque tout le reste dans un court laps de temps pour cet utilisateur particulier. rien de mal et rien de mal à ce sujet. (s'il est utilisé correctement, il ne bloquera rien car à ce moment-là, aucune autre action ne se produira pour cet utilisateur particulier)
low_rents

1
@northkildonan Non, ce n'est pas bien. Une demande de synchronisation AJAX est incorrecte. Il bloque le fil javascript complet avec quelque chose que vous ne pouvez pas contrôler. Vous n'avez pas de contrôle sur le temps que cela peut prendre pour traiter la demande: la connexion peut ne pas être fiable, le serveur peut prendre plus de temps que prévu, etc. La seule raison pour laquelle il est dans jQuery est que vous devrez peut-être enregistrer des données au déchargement de la page (le seul endroit où cela n'a pas vraiment d'importance si cela prend plus de temps, car l'utilisateur a déjà exprimé son désir de quitter la page). Regardez les tests unitaires jQuery…
nietonfir

3

C'est assez vieux et moche, ne faites pas ça. Vous devez utiliser des rappels: https://stackoverflow.com/a/5316755/591257
J'ai eu le même problème, l'a résolu de cette façon, en utilisant une variable globale. Je ne sais pas si c'est le meilleur mais ça marche sûrement. En cas d'erreur, vous obtenez une chaîne vide (myVar = ''), vous pouvez donc gérer cela selon vos besoins.

var myVar = '';
function isSession(selector) {
  $.ajax({
    'type': 'POST',
    'url': '/order.html',
    'data': {
      'issession': 1,
      'selector': selector
    },
    'dataType': 'html',
    'success': function(data) {
      myVar = data;
    },
    'error': function() {
      alert('Error occured');
    }
  });
  return myVar;
}

3
vous devez également ajouter async: falseici, car en mode asynchrone, il n'est pas garanti que l' dataenregistrement soit effectué myVaravant le myVarretour.
low_rents

2
// Common ajax caller
function AjaxCall(url,successfunction){
  var targetUrl=url;
  $.ajax({
    'url': targetUrl,
    'type': 'GET',
    'dataType': 'json',
    'success': successfunction,
    'error': function() {
      alert("error");
    }
  });
}

// Calling Ajax
$(document).ready(function() {
  AjaxCall("productData.txt",ajaxSuccessFunction);
});

// Function details of success function
function ajaxSuccessFunction(d){
  alert(d.Pioneer.Product[0].category);
}

cela peut aider, créer une fonction d'appel ajax commune et attacher une fonction qui invoquera en cas de succès l'appel ajax, voir l'exemple


1

Avec l'aide d' ici

function get_result(some_value) {
   var ret_val = {};
   $.ajax({
       url: '/some/url/to/fetch/from',
       type: 'GET',
       data: {'some_key': some_value},
       async: false,
       dataType: 'json'
   }).done(function (response) {
       ret_val = response;
   }).fail(function (jqXHR, textStatus, errorThrown) {
           ret_val = null;
       });
   return ret_val;
}

J'espère que cela aide un peu quelqu'un quelque part.


L'utilisation de async: false,est préhistorique et est obsolète depuis jQuery v1.8, cela n'aidera probablement personne
Alon Eitan

-2

Salut, essayez async: false dans votre appel ajax.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.