JavaScript détecter un événement AJAX

Ok donc fondamentalement je veux avoir un peu de javascript sur une page qui attache d'une façon ou d'une autre une sorte d'écouteur d'événement global qui peut détecter et faire quelque chose si une requête ajax est faite (sans l'appeler directement depuis l'appel), indépendamment de la façon dont l'appel ajax est fait.

j'ai trouvé comment faire avec jquery - si la requête ajax est faite par jquery. Voici un exemple de code:

$.post(
  // requested script
  'someScript.php', 
  // data to send
  {
    'foo' : 'bar',
    'a' : 'b'
  },
  // receive response
  function(response){
    // do something
  }
); // .post

// global event listener    
$(document).ajaxSend(
  function(event,request,settings){
    alert(settings.url); // output: "someScript.php"
    alert(settings.data); // output: "foo=bar&a=b"
  }
);

Avec ce code, peu importe où/comment j'appelle $.post.(.), le mondial de l'écouteur d'événement de déclenchement. Il fonctionne aussi si j'utilise $.obtenir ou $.ajax (toutes les méthodes ajax jquery), indépendamment de comment/quand je l'appelle (attaché comme un onclick, sur la charge de page, peu importe).

cependant, je veux pouvoir étendre cet écouteur pour déclencher quel que soit le framework js utilisé, ou même si aucun framework n'est utilisé. Donc par exemple si je devais aussi ont sur une page le code suivant (code ajax générique de w3schools):

function loadXMLDoc()
{
if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
  xmlhttp=new XMLHttpRequest();
  }
else
  {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.onreadystatechange=function()
  {
  if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
    }
  }
xmlhttp.open("GET","test.txt",true);
xmlhttp.send();
}

et puis j'ai sur quelque lien aléatoire un appel onclick à cette fonction, mon écouteur d'événements ajax global devrait être capable de aussi détecter cette requête. Eh bien, j'ai ajouté ce code à ma page et l'ai attaché à un clic de lien aléatoire (oui, le code lui-même fonctionne), mais le jquery" global event listener " code ci-dessus n'a pas réussi à détecter cet appel.

j'ai creusé un peu plus et je sais que je peux essentiellement sauver l'objet à un objet temp et écraser l'objet courant avec un objet" wrapper " qui appellera une fonction spécifiée puis appellera la fonction temp, mais cela exige que je sache à l'avance l'objet original étant créé/utilisé. Mais je ne le saurai pas toujours à l'avance...

alors...est-ce possible? Y a-t-il un moyen de détecter qu'une demande ajax get/post a été faite?, peu importe si cela a été fait avec un objet générique ou à partir du cadre xyz? Ou est-ce que je vais juste devoir faire du code dupliqué pour gérer chaque framework et aussi connaître à l'avance les objets ajax créés/utilisés?

edit:

j'ai oublié de mentionner qu'il ne suffit pas de détecter qu'une demande avait été faite. Je dois également saisir les données envoyées dans la demande. Le lien fourni dans les commentaires ci-dessous aidera à savoir si "une" requête a été fait, mais ne pas obtenir les données envoyées. p. S. - la réponse fournie dans le lien ci-dessous n'est pas très claire, du moins pour moi de toute façon.

68
demandé sur Crayon Violent 2010-08-30 01:04:40

2 réponses

Ok, c'est ce que j'ai jusqu'à présent:

<script type='text/javascript'>
var s_ajaxListener = new Object();
s_ajaxListener.tempOpen = XMLHttpRequest.prototype.open;
s_ajaxListener.tempSend = XMLHttpRequest.prototype.send;
s_ajaxListener.callback = function () {
  // this.method :the ajax method used
  // this.url    :the url of the requested script (including query string, if any) (urlencoded) 
  // this.data   :the data sent, if any ex: foo=bar&a=b (urlencoded)
}

XMLHttpRequest.prototype.open = function(a,b) {
  if (!a) var a='';
  if (!b) var b='';
  s_ajaxListener.tempOpen.apply(this, arguments);
  s_ajaxListener.method = a;  
  s_ajaxListener.url = b;
  if (a.toLowerCase() == 'get') {
    s_ajaxListener.data = b.split('?');
    s_ajaxListener.data = s_ajaxListener.data[1];
  }
}

XMLHttpRequest.prototype.send = function(a,b) {
  if (!a) var a='';
  if (!b) var b='';
  s_ajaxListener.tempSend.apply(this, arguments);
  if(s_ajaxListener.method.toLowerCase() == 'post')s_ajaxListener.data = a;
  s_ajaxListener.callback();
}
</script>

mode d'emploi:

Juste c/p cela sur votre page ou l'inclure dans une .le dossier js ou autre. Cela créera un objet appelé s_ajaxListener. Chaque fois qu'une requête AJAX GET ou POST est faite, s_ajaxListener.callback () est appelé, et les propriétés suivantes sont disponibles:

s_ajaxListener.méthode : la méthode ajax utilisée. Cela devrait être soit GET soit POST. NOTE: la valeur peut ne pas être toujours en majuscules, cela dépend de la façon dont la requête spécifique a été codée. Je suis en train de discuter de la sagesse de la superposer automatiquement ou de la laisser à quelque chose d'autre à toLowerCase() pour une comparaison sans sensibilité à la casse.

s_ajaxListener.url : l'url du script demandé (y compris la chaîne de requête, le cas échéant) (urlencoded). J'ai remarqué, selon la façon dont les données sont envoyées et depuis le navigateur ou le cadre, par exemple, cette valeur pourrait être que "" ou "+" ou "%20". Je discute de la sagesse de le décoder ici ou de le laisser à autre chose.

s_ajaxListener.données : les données transmises, le cas échéant ex: foo=bar&a=b (même "numéro" que .url avec l'url-encodé)

NOTES:

en l'état, ce n'est pas compatible IE6 . ce la solution n'est pas tout à fait assez bon pour moi, que je veux qu'il soit compatible IE6. Mais puisque beaucoup d'autres personnes ne se soucient pas de IE6, j'ai décidé de poster ma solution dans son état actuel, car il devrait fonctionner pour vous si vous ne vous souciez pas de IE6.

j'ai testé ceci dans (à partir de cette date postée): Safari actuel, Chrome actuel, FireFox actuel, IE8, IE8 (Compatible IE7). Il ne fonctionne pas actuellement avec IE6 parce que IE6 utilise un objet ActiveX, alors que pratiquement tout le reste utilise XMLHttpRequest.

en ce moment je n'ai aucune idée comment faire, en gros, prototype / extension / surcharge (?) ActiveXObject ("Microsoft.XMLHTTP"). C'est ce que je suis actuellement à la recherche...quelqu'un sait désinvolte?

sous chacun des navigateurs que j'ai testés ci-dessus, cela fonctionne avec les requêtes AJAX d'un objet générique, ainsi que des cadres jQuery et prototype. Je sais qu'il y a d'autres cadres là-bas, mais IMO ces 2 sont les plus importantes. J'ai peut-être des outils de QA, mais à part ça, ça me va de les tester.

si Quelqu'un veut contribuer en testant et en affichant des résultats sur d'autres navigateurs et/ou cadres, il serait apprécié:)

100
répondu Crayon Violent 2014-08-15 15:02:17

pour la compatibilité IE 6, Que diriez-vous de:

<script type='text/javascript'>
  var s_ajaxListener = new Object();

  // Added for IE support
  if (typeof XMLHttpRequest === "undefined") {
    XMLHttpRequest = function () {
      try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
      catch (e) {}
      try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
      catch (e) {}
      try { return new ActiveXObject("Microsoft.XMLHTTP"); }
      catch (e) {}
      throw new Error("This browser does not support XMLHttpRequest.");
    };
  }

  s_ajaxListener.tempOpen = XMLHttpRequest.prototype.open;
  s_ajaxListener.tempSend = XMLHttpRequest.prototype.send;
  s_ajaxListener.callback = function () {
    // this.method :the ajax method used
    // this.url    :the url of the requested script (including query string, if any) (urlencoded) 
    // this.data   :the data sent, if any ex: foo=bar&a=b (urlencoded)
  }

  XMLHttpRequest.prototype.open = function(a,b) {
    if (!a) var a='';
    if (!b) var b='';
    s_ajaxListener.tempOpen.apply(this, arguments);
    s_ajaxListener.method = a;  
    s_ajaxListener.url = b;
    if (a.toLowerCase() == 'get') {
      s_ajaxListener.data = b.split('?');
      s_ajaxListener.data = s_ajaxListener.data[1];
    }
  }

  XMLHttpRequest.prototype.send = function(a,b) {
    if (!a) var a='';
    if (!b) var b='';
    s_ajaxListener.tempSend.apply(this, arguments);
    if(s_ajaxListener.method.toLowerCase() == 'post')s_ajaxListener.data = a;
    s_ajaxListener.callback();
  }
</script>
5
répondu Sébastien Brodeur 2014-05-14 13:48:21