JavaScript обнаруживает событие AJAX
Итак, в основном я хочу разместить на странице немного 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();
}
И затем, по какой-то случайной ссылке, с помощью функции onclick вызывается эта функция, мой глобальный прослушиватель ajax-событий должен иметь возможность обнаруживать этот запрос. Ну, я добавил этот код на свою страницу и прикрепил его к щелчку произвольной ссылки (да, сам код работает), но приведенный выше код jquery "слушатель глобального события" не смог обнаружить этот вызов.
Я сделал еще несколько копаний и знаю, что в принципе могу сохранить объект во временном объекте и перезаписать текущий объект объектом-оболочкой, который вызовет указанную функцию, а затем вызовет временную функцию, но для этого нужно знать заранее время создания / использования исходного объекта. Но я не всегда буду знать, что раньше...
Итак... это возможно? Есть ли какой-нибудь способ обнаружить ajax-запрос get / post, независимо от того, был ли он сделан с универсальным объектом или из фреймворка xyz? Или мне просто нужно будет создать дублирующий код для обработки каждой среды, а также заранее знать, какие объекты / объекты ajax создаются / используются?
редактировать:
Я забыл упомянуть, что недостаточно обнаружить запрос. Мне также нужно захватить данные, отправляемые в запросе. Ссылка, приведенная в комментариях ниже, поможет выяснить, был ли сделан запрос "а", но не получить отправленные данные. ps - ответ, приведенный в ссылке ниже, не очень понятен, по крайней мере, для меня в любом случае.
3 ответа
Хорошо, это то, что я придумал до сих пор:
<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 и prototype. Я знаю, что есть другие структуры, но IMO, эти 2 являются основными. Я мог бы, возможно, QA MooTools, но кроме этого, я в порядке только с тестированием тех.
Если кто-то захочет внести свой вклад путем тестирования и публикации результатов о других браузерах и / или фреймворках, это будет оценено:)
Для совместимости с 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>
Имея необходимость прослушивать события AJAX с помощью других скриптов (либо XHR, либо fetch) и вдохновленный этим сообщением SO, я создал небольшую утилиту, которая довольно универсальна, AjaxListener.js на GitHub (примечание: IE < 7 НЕ поддерживается ).
Основное использование:
function mylistener(req, res)
{
// API is either 'xhr' or 'fetch'
console.log('REQUEST', 'API', req.getAPI(), 'Method', req.getMethod(), 'URL', req.getURL(), 'Headers', req.getHeaders(), 'Body', req.getBody());
console.log('RESPONSE', 'API', res.getAPI(), 'Status', res.getStatus(), 'URL', res.getURL(), 'Headers', res.getHeaders(), 'Body', res.getBody());
}
AjaxListener.install().onRequest(mylistener);
//AjaxListener.onRequest(mylistener, false); // unlisten
//AjaxListener.uninstall(); // uninstall
Надеюсь, это полезно.