2017-10-19 33 views
0

Je voudrais tester si la requête ajax est identique afin qu'elle puisse être annulée ou qu'une autre action d'alerte soit prise?Éviter une demande ajax client identique à l'actualisation

En réalité, les clients peuvent modifier la demande via quelques éléments de formulaire, puis appuyer sur le bouton d'actualisation.

J'ai fait une mauvaise tentative pour attraper la même demande. Besoin de garder la fonctionnalité d'actualisation de la minuterie.

<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script> 

<script type="text/javascript"> 

    var current_request_id = 0; 
    var currentRequest = null; 
    var lastSuccessfulRequest = null; 

    function refreshTable() { 
     $('#select').html('Loading'); 
     window.clearTimeout(timer); 

     //MY CATCH FOR DUPLICATE REQUEST NEEDS WORK 
     if (lastSuccessfulRequest == currentRequest) 
     { 
      //currentRequest.abort(); 
      alert('Duplicate query submitted. Please update query before resubmission.'); 
     } 

     var data = { 
      "hide_blanks": $("#hide_blanks").prop('checked'), 
      "hide_disabled": $("#hide_disabled").prop('checked'), 
     }; 

     json_data = JSON.stringify(data); 

     current_request_id++; 
     currentRequest = $.ajax({ 
      url: "/calendar_table", 
      method: "POST", 
      data: {'data': json_data}, 
      request_id: current_request_id, 
      beforeSend : function(){ 
       if(currentRequest != null) { 
        currentRequest.abort(); 
       } 
      }, 
      success: function(response) { 
       if (this.request_id == current_request_id) { 
        $("#job_table").html(response); 
        $("#error_panel").hide(); 
        setFixedTableHeader(); 
       } 
      }, 
      error: function(xhr) { 
       if (this.request_id == current_request_id) { 
        $("#error_panel").show().html("Error " + xhr.status + ": " + xhr.statusText + "<br/>" + xhr.responseText.replace(/(?:\r\n|\r|\n)/g, "<br/>")); 
       } 
      }, 
      complete: function(response) { 
       if (this.request_id == current_request_id) { 
        $("#select").html("Refresh"); 
        window.clearTimeout(timer); 
        stopRefreshTable(); 
        window.refreshTableTimer = window.setTimeout(refreshTable, 10000); 

        lastSuccessfulRequest = currentRequest; 
       } 
      } 
     }); 
    } 




    //TIMER STUFF TO refreshTable() 
    //THIS SECTION WORKS FINE 
    var startDate = new Date(); 
    var endDate = new Date(); 
    var timer = new Date(); 
    function startRefreshTable() { 
     if(!window.refreshTableTimer) { 
      window.refreshTableTimer = window.setTimeout(refreshTable, 0); 
     } 
    } 
    function stopRefreshTable() { 
     if(window.refreshTableTimer) { 
      self.clearTimeout(window.refreshTableTimer); 
     } 
     window.refreshTableTimer = null; 
    } 
    function resetActive(){ 
     clearTimeout(activityTimeout); 
     activityTimeout = setTimeout(inActive, 300000); 
     startRefreshTable(); 
    } 

    function inActive(){ 
     stopRefreshTable(); 
    } 
    var activityTimeout = setTimeout(inActive, 300000); 
    $(document).bind('mousemove click keypress', function(){resetActive()}); 

</script> 


<input type="checkbox" name="hide_disabled" id="hide_disabled" onchange="refreshTable()">Hide disabled task<br> 
<br><br> 
<button id="select" type="button" onclick="refreshTable();">Refresh</button> 
+1

"est identique" ... identique à quoi, précisément? La demande précédente? Toute demande précédente? Autre chose? Et identique dans quel sens? Du même utilisateur? Les mêmes paramètres? Les mêmes en-têtes? Veuillez clarifier vos exigences précises. La façon dont vous le faites maintenant est naïve. $ .ajax renvoie un objet Deferred, que vous ne pouvez pas vraiment comparer pour "égalité" d'une manière significative avec un autre, et ne vous dit rien sur le contenu de la requête - il est conçu pour vous ajouter des rappels afin de gérer la réponse. Une fois que vous aurez clarifié ce que vous voulez dire, nous pourrons trouver une meilleure façon de le faire. – ADyson

+1

Également une note de côté: '.bind' de jQuery a été remplacé par' .on' dans jQuery 1.7, et est maintenant complètement obsolète. Il ne devrait y avoir aucune raison de toujours l'utiliser, ou pire, de l'utiliser pour un nouveau code. http://api.jquery.com/bind/ – ADyson

+0

Sûrement il y a un moyen de faire votre point sans poster une centaine de lignes de code. Lisez et suivez [mcve]. – Tomalak

Répondre

0

j'utiliser la puissance de .ajaxSend et .ajaxSuccess gestionnaires mondiaux. Nous allons utiliser ajaxSuccess pour stocker un cache et ajaxSend essayera de le lire en premier, s'il réussit, il déclenchera immédiatement le gestionnaire de succès de la requête et abandonnera la requête qui est sur le point d'être effectuée. Sinon, il va que ce soit ...

var ajax_cache = {}; 
function cache_key(settings){ 
    //Produce a unique key from settings object; 
    return settings.url+'///'+JSON.encode(settings.data); 
} 
$(document).ajaxSuccess(function(event,xhr,settings,data){ 
    ajax_cache[cache_key(settings)] = {data:data}; 
    // Store other useful properties like current timestamp to be able to prune old cache maybe? 
}); 
$(document.ajaxSend(function(event,xhr,settings){ 
    if(ajax_cache[cache_key(settings)]){ 
     //Add checks for cache age maybe? 
     //Add check for nocache setting to be able to override it? 
     xhr.abort(); 
     settings.success(ajax_cache[cache_key(settings)].data); 
    } 
}); 

Ce que je l'ai démontré ici est une approche très naïve, mais fonctionnelle à votre problème. Cela a l'avantage de faire ce travail pour tous les appels ajax que vous pourriez avoir, sans avoir à les changer. Vous devez construire sur ceci pour considérer des échecs, et pour s'assurer que l'avortement de la demande d'un succès de cache n'est pas envoyé pour avorter des gestionnaires.

0

Une option valide ici est de JSON.Stringify() les objets et de comparer les chaînes. Si les objets sont identiques, les chaînes sérialisées résultantes doivent être identiques.

Il peut y avoir des cas de bords provoquant de légères différences si vous utilisez une chaîne déjà nommée JSONified directement à partir de la réponse, vous devrez donc vérifier en testant.

En outre, si vous tentez de savoir comment le conserver sur plusieurs pages, utilisez localStorage.setItem("lastSuccessfulRequest", lastSuccessfulRequest) et localStorage.getItem("lastSuccessfulRequest"). (Si non, faites le moi savoir et je vais supprimer cela.)