JavaScript detect an AJAX event

Okay so basically I want to have a bit of javascript on a page that somehow attaches some kind of global event listener that can detect and do something if an ajax request is made (without directly calling it from the call), regardless of how the ajax call is made.

I figured out how to do this with jquery - if the ajax request is being done by jquery. Here is an example code for this:

$.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"
  }
);

With this code, regardless of where/how I call $.post(..), the global event listener will trigger. It also works if I use $.get or $.ajax (any jquery ajax methods), regardless of how/when I call it (attached as an onclick, on page load, whatever).

However, I want to be able to extend this listener to trigger regardless of what js framework is used, or even if no framework is used. So for instance if I were to also have on a page the following code (generic ajax code from 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();
}

And then I have on some random link an onclick call to that function, my global ajax event listener should be able to also detect this request. Well I added that code to my page and attached it to a random link's onclick (yes, the code itself works), but the jquery "global event listener" code above failed to detect that call.

I did some more digging and I know I can basically save the object to a temp object and overwrite the current object with a "wrapper" object that will call a specified function and then call the temp function, but this requires me to know ahead of time the original object being created/used. But I won't always know that ahead of time...

So...is this possible? Is there some way to detect an ajax get/post request was made, regardless of whether it was done with a generic object or from xyz framework? Or am I just going to have to make duplicate code to handle each framework and also know ahead of time the ajax object(s) being created/used?

edit:

I forgot to mention that it is not enough to detect that a request occurred. I also need to capture the data being sent in the request. The link provided in the comments below will help figure out if "a" request was made, but not get the data sent. p.s. - the answer provided in the link below is not very clear, at least to me anyways.

71
задан Crayon Violent 30 August 2010 в 00:32
поделиться

1 ответ

Хорошо, вот что я придумал на данный момент:

<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>

НАПРАВЛЕНИЯ:

Просто скопируйте это на свою страницу или включите в файл .js или что-то еще. Это создаст объект с именем s_ajaxListener. Всякий раз, когда делается запрос AJAX GET или POST, вызывается s_ajaxListener.callback(), и доступны следующие свойства:

s_ajaxListener.method : используемый метод ajax. Это должно быть GET или POST. ПРИМЕЧАНИЕ: значение не всегда может быть в верхнем регистре, это зависит от того, как был закодирован конкретный запрос. Я обсуждаю целесообразность автоматического перевода в верхний регистр или предоставления чего-то другого toLowerCase() для сравнения без учета регистра.

s_ajaxListener.url : URL-адрес запрошенного скрипта (включая строку запроса, если она есть) (urlencoded). Я заметил, что в зависимости от того, как данные отправляются и из какого браузера/фреймворка, например, это значение может иметь вид " ", "+" или "%20". Я обсуждаю целесообразность расшифровки здесь или оставляю это для чего-то другого.

s_ajaxListener.data : отправленные данные, если таковые имеются, например: foo=bar&a=b (та же «проблема», что и .url, но с кодировкой URL)

ПРИМЕЧАНИЯ:

В нынешнем виде, это несовместимо с IE6. это решение мне не совсем подходит, так как я хочу, чтобы оно было совместимо с IE6. Но так как многим другим людям наплевать на IE6, я решил опубликовать свое решение в его текущем состоянии, так как оно должно сработать для вас, если вам наплевать на IE6.

Я тестировал это в (на дату публикации): Текущий Safari, Текущий Chrome, Текущий FireFox, IE8, IE8 (совместимый с IE7).В настоящее время он не работает с IE6, потому что IE6 использует объект ActiveX, тогда как практически все остальное использует XMLHttpRequest.

Прямо сейчас я понятия не имею, как создать прототип/расширить/перегрузить (?) ActiveXObject("Microsoft.XMLHTTP"). Это то, что я сейчас исследую ... кто-нибудь знает навскидку?

В каждом из браузеров, которые я тестировал выше, это работает с запросами AJAX от универсального объекта, а также от каркасов jquery и прототипов. Я знаю, что есть и другие фреймворки, но эти 2 являются основными. Я мог бы, возможно, QA MooTools, но кроме этого, я в порядке, только тестируя их.

Если кто-то захочет внести свой вклад, протестировав и опубликовав результаты других браузеров и/или фреймворков, мы будем признательны :)

101
ответ дан 24 November 2019 в 13:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: