JavaScript виявляє подію AJAX


78

Гаразд, отже, в основному я хочу мати трохи 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), незалежно від того, як / коли я їх викликаю (додається як натискання, при завантаженні сторінки, що завгодно).

Однак я хочу мати можливість розширити цей прослуховувач для запуску незалежно від того, який 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();
}

І тоді я на якому - то випадковому зв'язати OnClick виклик цієї функції, мій глобальний Аякса слухач подій повинен мати можливість також виявити цей запит. Ну, я додав цей код на свою сторінку і прикріпив його до onclick випадкового посилання (так, сам код працює), але наведений вище код jquery "прослуховувач глобальних подій" не вдалося виявити цей виклик.

Я ще трохи копав, і знаю, що в основному можу зберегти об'єкт у тимчасовий об'єкт і переписати поточний об'єкт об'єктом "обгортка", який викликатиме визначену функцію, а потім викликатиме функцію temp, але для цього потрібно знати наперед час створення / використання оригінального об'єкта. Але я не завжди буду знати, що раніше часу ...

Отже ... чи можливо це? Чи є спосіб виявити зроблений запит ajax get / post, незалежно від того, чи було це зроблено із загальним об’єктом, або з фреймворку xyz? Або мені просто доведеться створити повторюваний код для обробки кожного фреймворку, а також заздалегідь знати, які об’єкти (файли) ajax створюються / використовуються?

редагувати:

Я забув згадати, що недостатньо виявити, що запит стався. Мені також потрібно отримати дані, що надсилаються у запиті. Посилання в коментарях нижче допоможе з’ясувати, чи було зроблено запит "a", але не отримати дані. ps - відповідь, надана за посиланням нижче, не дуже зрозуміла, принаймні для мене в будь-якому випадку.



Дякую за посилання! Це питання не зовсім схоже на це, тому що мені потрібно було також мати можливість фіксувати дані, що надсилаються у запиті (які, мабуть, я нехтував включити; відредаговано в). Однак це ВИСОКУВ мене на правильному шляху, і я думаю, що знайшов рішення, опублікую, коли тестування буде завершено. Дякую!
Crayon Violent

Я думаю , що ви шукаєте в цьому питанні про маніпулювання прототип , але в кращу сторону stackoverflow.com/q/20689481/3462483
doz87

Відповіді:


108

Гаразд, ось що я придумав до цього часу:

<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-адреса запитуваного сценарію (включаючи рядок запиту, якщо такий є) (закодований). Я помітив, що залежно від того, як дані надсилаються та з якого браузера / фреймворку, наприклад, це значення може мати значення "" або "+" або "% 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 та prototype. Я знаю, що існують інші рамки, але IMO - це два основних. Я, можливо, QA MooTools, але крім цього, я в порядку з тестуванням лише тих.

Якщо хтось хоче зробити свій внесок, протестуючи та розмістивши результати про інші браузери та / або фреймворки, це буде вдячно :)


1
Ви можете визначити функцію обгортки для IE6, як це робить Сарісса ; подивіться на Повторне винахід XMLHttpRequest, щоб побачити, як це можна зробити (зараз у мене немає часу). Ви не можете розширити об’єкт ActiveX, але ви можете розширити власну функцію обгортки, яка просто емулює необхідні властивості. Я думаю, що більшість бібліотек перевіряють наявність window.XMLHttpRequestі ваш об’єкт-обгортка буде виявлений.
Марсель Корпель

Також зверніть увагу, що IE8 у режимі сумісності IE7 ≠ IE7. Я підозрюю, що XMLHttpRequestоб'єкт є однією з речей, що відрізняються: в IE7 це, здається, просто функція обгортки над компонентом ActiveX, тоді як в IE8 він може бути реалізований як "справжній" об'єкт XHR.
Марсель Корпель

1
В даний час не працює у FireFox. Виправлено помилки XMLHttpRequest.open.apply
HMR

Все ще працює чудово, але з якихось причин XMLHttpRequest.sendвикликається кожен клік у Chrome, а зворотний виклик закінчується виконанням кожного кліку
Петр Газаров

@PetrGazarov цікаво .. Цікаво, чи це якийсь побічний ефект попереднього вибору?
Crayon Violent

5

Що стосується сумісності з 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>

6
так, це майже те, що я робив у той час .. але IE6 - це те, що більше ніхто не повинен підтримувати, тим більше, що Microsoft сама припинила його підтримку (за рахунок непідтримки XP) станом на квітень 2014
Crayon Violent
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.