2009-12-15 14 views
24

Nous utilisons gestionnaire ajaxError global() jQuery pour alerter l'utilisateur de toute défaillance AJAX:jQuery feux de gestionnaire ajaxError() si l'utilisateur quitte la page avant la page se termine le chargement

$(document).ajaxError(function() { 
    $("There was a network or server error. Please try again later.").dialog({ 
     title: "Error", 
     modal: true, 
     resizable: false, 
     buttons: { 'Ok': function() { (this).dialog("close"); } } 
    }); 
}); 

Malheureusement, ce gestionnaire d'erreur global déclenche également si l'utilisateur quitte la page avant la fin du chargement. Voici les étapes pour reproduire l'erreur:

  1. Visites d'utilisateur Page A, qui inclut des éléments qui se chargent via AJAX.
  2. Les éléments AJAX de la page A commencent à être chargés.
  3. L'utilisateur clique sur le lien pour visiter la page B avant Les éléments AJAX de la page A ont terminé le chargement.
  4. La boîte de dialogue d'erreur apparaît brièvement avant que le navigateur redirige vers la page B.

Toute idée de comment nous pouvons obtenir ajaxError() ne pas déclencher lorsque l'erreur est causée directement par l'utilisateur visite une nouvelle page?

MISE À JOUR: Voici mon code maintenant, après avoir intégré les suggestions dans les commentaires:

// I added a 3 second delay to our error dialog, enough time 
// for the user to leave for a new page: 
$(document).ajaxError(function() { 
    setTimeout(my_error_handler, 3000); 
}); 

// Warn user before leaving page if AJAX is still loading. 
// Not sure I'll keep this: 
$(document).ajaxStart(function() { 
    ajaxing = true; 
}); 

$(document).ajaxStop(function() { 
    ajaxing = false; 
}); 

window.onbeforeunload = function() { 
    if (typeof(ajaxing) != 'undefined' && ajaxing) { 
     return "Page elements are still loading!"; 
    } 
}; 

Répondre

15

Eh bien oui, si l'utilisateur accède à une autre page, le XHR abandonnera, ce qui est, en effet, un échec la communication. Une solution consisterait à enregistrer un écouteur pour l'événement onbeforeunload, et de lier ici ajaxError, en disant essentiellement: l'utilisateur est sur le point de quitter la page, donc je ne souhaite pas être informé des erreurs ajax qui pourraient suivre. Cependant, certains sites, comme GMail, font l'inverse: si vous essayez de vous éloigner de la page alors qu'il y a encore des requêtes ajax en attente, il vous donne une invite indiquant que vous avez encore des processus en cours d'exécution, et permet à l'utilisateur de décider s'il doit rester sur le site jusqu'à ce que la demande soit terminée, ou d'aller de l'avant et de s'en aller.

+2

L'approche GMail est bien meilleure! – TheVillageIdiot

+2

Eh oui, si vous devez avoir une approche générale, je suppose que c'est ce que je préfère aussi. Bien que je voudrais bien plus si un drapeau a été passé à la fonction faisant l'appel ajax, déterminer si la demande actuelle était critique ou non. c'est-à-dire si la requête est juste une session keep-alive, ou une vérification de nouveaux messages, ou quelque chose, vous pouvez laisser cet abandon s'interrompre silencieusement. –

+0

David, merci pour la suggestion. Je n'ai pas encore testé les navigateurs supportant la fonction onbeforeunload, mais cela fonctionne bien sur FF 3.5 jusqu'à présent. J'ai également ajouté un délai de 3 secondes à la boîte de dialogue d'erreur (une suggestion d'un commentaire précédent qui semble être supprimée maintenant.) – richardkmiller

10

Sur la base de la réponse de David Hedlund ci-dessus voici le code qui fonctionne pour moi:

//enable global ajax error handling 
$(document).ajaxError(function (event, request, settings) { 
    //your error handling code here 
}); 

//user leaving page so ignore any unfinished ajax loads 
$(window).bind('beforeunload', function() { 
    $(document).unbind('ajaxError'); 
}); 

J'ai obtenu la spécification 'ajaxError' de la section des commentaires de jquery ajaxError documentation. J'ai dû lier beforeunload à $(window) afin de soutenir le chrome (IE fonctionnait bien avec le document). .ajaxError n'a pas déclenché lorsque j'ai été lié à $(window), c'est pourquoi j'ai cette solution de fenêtre/document.