Dernièrement, je cherchais à effectuer une action supplémentaire en cas de succès d’un appel Ajax : en effet, dans l’application que je développe, j’ai un contrôleur principal, par lequel passent toutes les requêtes, et qui vérifie si l’utilisateur est bien connecté – dans le cas contraire, il le redirige vers la page de connexion. Mais dans le cas d’une page laissée à l’abandon suffisamment longtemps pour que la session expire, et où l’utilisateur ne recharge pas, mais effectue une action qui appelle le serveur via XMLHttpRequest (Ajax, en gros), eh bien, la redirection ne se faisait pas comme je le voulais.
En effet, les spécifications du W3C indiquent que si l’origine de la source et l’origine de l’URL demandée sont la même, alors le navigateur doit suivre silencieusement la redirection, tout en observant les règles d’évenements s’appliquant aux requêtes de même origine.
((If the source origin and the origin of request URL are same origin transparently follow the redirect while observing the same-origin request event rules.
Source : http://www.w3.org/TR/XMLHttpRequest/#infrastructure-for-the-send-method ))
Par conséquent, comme la fonction JavaScript exécutée en retour de mon appel affichait des informations dans un élément de la page, à cause de la redirection, c’était la page de connexion qui se retrouvait dans cet élément. Donc, il me fallait trouver un moyen de rediriger correctement. Et pour cela, j’ai fait ce que Paul Irish appelle du duck punching ! L’idée est tout simplement de redéfinir une fonction de base pour qu’elle renvoie autre chose.
Ici, je court-circuite la méthode jQuery.ajax, en conservant l’ancienne méthode dans une variable :
var _old = $.ajax;
…et aussi l’objet (success) que je vais modifier :
var _oSuccess = options.success; // on conserve la référence de base à l'objet
…en précisant que si je reçois une réponse particulière :
if(response.deconnexion_utilisateur == true)
…alors je fais une action particulière :
location.href = response.url ;
return false;
…sinon on réinjecte l’objet de base :
_oSuccess(response); // on réinjecte l'objet
Dans tous les cas, on lance l’ancienne fonction, avec, peut-être, les nouveaux arguments :
return _old.call(this,options);
Ce qui nous donne au final :
(function($){
var _old = $.ajax; // on conserve la référence de base à la méthode
$.ajax = function(options){
var _oSuccess = options.success; // on conserve la référence de base à l'objet
options.success = function(response) {
if(response.deconnexion_utilisateur == true){
// on redirige vers la connexion
location.href = response.url ;
return false;
}
else {
_oSuccess(response); // on réinjecte l'objet
}
}
// on appelle l'ancienne méthode avec les nouveaux arguments
return _old.call(this,options);
};
})(jQuery);