JavaScript обнаруживает событие AJAX - PullRequest
71 голосов
/ 30 августа 2010

Хорошо, в общем, я хочу разместить на странице немного javascript, который каким-то образом присоединяет некоторый глобальный слушатель событий, который может обнаруживать и делать что-то, если сделан запрос ajax (без непосредственного вызова из вызова), независимо откак осуществляется вызов AJAX.

Я понял, как это сделать с помощью jquery - если запрос ajax выполняется с помощью jquery.Вот пример кода для этого:

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

С этим кодом, независимо от того, где / как я вызываю $ .post (..), сработает глобальный прослушиватель событий.Это также работает, если я использую $ .get или $ .ajax (любые методы jquery ajax), независимо от того, как / когда я его вызываю (прикрепляется как onclick, при загрузке страницы, как угодно).

Однако я хочу иметь возможность расширять этот слушатель для запуска независимо от того, какая среда js используется, или даже если никакая структура не используется.Так, например, если бы я также имел на странице следующий код (универсальный код ajax из 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();
}

А потом у меня на некоторыхПри случайном соединении вызова этой функции одним щелчком мой глобальный слушатель событий ajax должен иметь возможность также обнаруживать этот запрос.Я добавил этот код на свою страницу и прикрепил его к щелчку произвольной ссылки (да, сам код работает), но приведенный выше код jquery «глобальный прослушиватель событий» не смог обнаружить этот вызов.

Я сделал еще несколько копаний, и я знаю, что в принципе могу сохранить объект во временном объекте и перезаписать текущий объект объектом-оберткой, который вызовет указанную функцию, а затем вызовет временную функцию, но этотребует, чтобы я заранее знал, какой исходный объект создается / используется.Но я не всегда буду знать, что раньше ...

Так ... это возможно?Есть ли какой-нибудь способ обнаружить ajax-запрос get / post, независимо от того, был ли он сделан с универсальным объектом или из фреймворка xyz?Или мне просто нужно будет создать дублирующий код для обработки каждой среды, а также заранее знать, какие объекты / объекты ajax создаются / используются?

edit:

Я забыл упомянутьчто этого недостаточно, чтобы обнаружить, что запрос произошел.Мне также нужно захватить данные, отправляемые в запросе.Ссылка, приведенная в комментариях ниже, поможет выяснить, был ли сделан запрос «а», но не получить отправленные данные.ps - ответ, приведенный в ссылке ниже, не очень понятен, по крайней мере, для меня в любом случае.

Ответы [ 2 ]

101 голосов
/ 30 августа 2010

Хорошо, это то, что я придумала до сих пор:

<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 и прототипов.Я знаю, что есть другие структуры, но IMO эти 2 являются основными.Я мог бы, возможно, QA MooTools, но кроме этого, я в порядке только с тестированием тех.

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

5 голосов
/ 14 мая 2014

Для совместимости с IE 6, как насчет:

<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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...