web-dev-qa-db-fra.com

Appel jQuery Ajax - Définir la valeur de la variable en cas de succès

J'ai une application que j'écris qui modifie les données sur un objet mis en cache sur le serveur. Les modifications sont effectuées via un appel ajax qui met à jour les propriétés de cet objet. Lorsque l'utilisateur a terminé de travailler, j'ai un bouton de base "Enregistrer les modifications" qui lui permet d'enregistrer les données et de vider l'objet mis en cache.

Afin de protéger l'utilisateur, je veux les avertir si vous essayez de vous éloigner de la page lorsque des modifications ont été apportées à l'objet serveur si elles n'ont pas été enregistrées. J'ai donc créé une méthode de service Web appelée IsInitialized qui retournera vrai ou faux selon que les modifications ont été enregistrées ou non. S'ils n'ont pas été enregistrés, je souhaite inviter l'utilisateur et lui donner la possibilité d'annuler sa demande de navigation.

Voici mon problème - bien que les appels fonctionnent correctement, je n'arrive pas à obtenir l'appel de succès ajax pour définir la valeur de la variable sur sa fonction de rappel. Voici le code que j'ai maintenant.

   ////Catches the users to keep them from navigation off the page w/o saved changes...
window.onbeforeunload = CheckSaveStatus;
var IsInitialized;

function CheckSaveStatus() {

    var temp = $.ajax({
        type: "POST",
        url: "URL.asmx/CheckIfInstanceIsInitilized",
        data: "{}",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function(result) {
            IsInitialized = result.d;
        },
        error: function(xmlHttpRequest, status, err) {
            alert(xmlHttpRequest.statusText + " " + xmlHttpRequest.status + " : " + xmlHttpRequest.responseText);
        }

    });

    if (IsInitialized) {
        return "You currently have unprocessed changes for this Simulation.";
    }
}

Je pense que j'essaie d'utiliser le rappel Success de manière inappropriée. Comment puis-je définir une variable javascript sur le rappel Success afin que je puisse décider si l'utilisateur doit ou non être invité avec le message de modifications non enregistrées?

Comme je viens de le souligner, je fais un appel asynchrone, ce qui signifie que le reste du code est appelé avant le retour de ma méthode. Existe-t-il un moyen d'utiliser cet appel ajax, mais d'attraper toujours l'événement window.onunload? (sans faire de synchronos ajax)

44
Nathan

Étant donné que vous avez besoin de ce comportement dans l'événement de déchargement, vous devrez effectuer un appel synchrone à la place. Cependant, cela peut geler la fenêtre/l'onglet du navigateur en fonction de la durée de l'appel, mais parce que vous essayez effectivement d'empêcher l'utilisateur de fermer la fenêtre ...

Ajouter async: false à votre JSON pour effectuer un appel synchrone.

36
Pawel Krakowiak

Un exemple de page jquery:

var html = $.ajax({
  url: "some.php",
  async: false
 }).responseText;

Source: http://api.jquery.com/jQuery.ajax/

7
Vale

Le fait est que la demande d'appel Ajax est asynchrone. Donc, au moment où vous vérifiez que vous êtes initialisé, l'appel n'est pas encore terminé.

Je suggère de spécifier votre comportement dans la fonction de réussite.

Fondamentalement, avoir des appels synchrones avec ajax est sinon impossible que vraiment découragé.

4
Rashack

J'ai eu un problème similaire avec la tentative de définition d'une propriété pour un objet de données via le rappel de succès d'une demande ajax. En utilisant async: false n'a pas non plus résolu mon problème. Ce que j'ai fini par faire était d'utiliser un appel setTimeout en dehors de l'appel ajax, et de définir la valeur du délai d'expiration sur 1, comme ceci:

function getSessionid() {  
    $.ajax({  
        type: 'POST',  
        url: 'getSession.php',  
        dataType: 'text',  
        success: function(result){myData.sessionid = result;},   
        error: function(data) {alert("Error!\n" + data);} 
    });  
    setTimeout(function() {alert('sessionid = ' + myData.sessionid);},1);  
}  

Le simple fait d'avoir ce retard d'une milliseconde a fait toute la différence dans le monde. Sans elle, la propriété sessionid ne serait pas définie en dehors de l'appel ajax, bien que des alertes dans le rappel aient montré qu'elle était effectivement définie. C'est quelque chose à penser, si vous rencontrez un problème similaire.

2
GeekCaveCreations

Vous pouvez théoriquement tuer l'événement (renvoyer false) et fermer la fenêtre en cas de succès, mais je pense que vous rencontreriez des restrictions Javascript définies par certains utilisateurs, et les confondriez simplement pour expliquer pourquoi leur fenêtre ne se ferme pas. Donc, je suis d'accord avec Pawel Krakowiak, l'appel ajax lui-même doit être synchrone.

J'ajouterai que vous voudrez informer l'utilisateur que vous vérifiez l'état (pas une fenêtre contextuelle, s'il vous plaît. Une de ces belles bannières de notification en haut de la fenêtre) et assurez-vous de définir le $ .ajax "timeout" option à quelque chose de plus raisonnable pour cette situation, donc ils n'attendent pas éternellement la fermeture de la fenêtre.

2
Jerph

Il semble que la meilleure approche pour moi était d'utiliser l'option async: false sur mon appel ajax. Bien que je comprenne l'hésitation de Rashack à le faire, je pense que cette situation justifie les moyens.

Un autre point important de Jerph à propos de s'assurer que je ne laisse pas l'utilisateur suspendu pendant que j'essaie de vérifier son statut. Ce couplé avec l'option de délai d'attente est important.

Merci à tous ceux qui ont commenté.

1
Nathan
0
sissi