2010-08-29 4 views
65

Итак, в основном, я хочу иметь немного javascript на странице, которая каким-то образом присоединяет какой-то глобальный прослушиватель событий, который может обнаруживать и делать что-либо, если выполняется запрос ajax (без прямого вызова его из вызов), независимо от того, как выполняется вызов ajax.JavaScript обнаруживает событие 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 должен иметь возможность также обнаружить этот запрос. Ну, я добавил этот код на свою страницу и привязал его к onclick случайной ссылки (да, сам код работает), но код jQuery «global event listener» выше не смог обнаружить этот вызов.

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

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

редактировать:

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

+4

возможный дубликат [ Выяснение, когда запрос XMLHttpRequest был выполнен без обратных вызовов] (http://stackoverflow.com/questions/2255248/figuring-out-when-a-xmlhttprequest-request-was-made-without-callbacks) –

+0

Спасибо за ссылку! Этот вопрос не совсем такой, потому что мне нужно было также уловить данные, отправляемые в запросе (которые, как я полагаю, я забыл включить, отредактировал). Тем не менее, это привело меня к правильному пути, и я думаю, что нашел решение, опубликую, когда тестирование будет завершено. Благодаря! –

+0

Я думаю, что вы ищете в этом вопросе о том, как манипулировать прототипом, но лучше. Https://stackoverflow.com/q/20689481/3462483 – doz87

ответ

99

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

<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. Всякий раз, когда АЯКС GET или POST-запрос сделан, s_ajaxListener.callback() вызывается, и доступны следующие свойства:

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

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

s_ajaxListener.data: данные отправлены, если таковые например: Foo = & бар а = Ь (то же самое 'выпуск', как .url с ним быть URL-кодировке)

ПРИМЕЧАНИЯ:

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

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

Прямо сейчас у меня нет никакой подсказки, как, ну в основном прототип/extend/overload (?) ActiveXObject («Microsoft.XMLHTTP»). Это то, что я сейчас изучаю ... кто-нибудь знает небрежно?

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

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

+1

Вы можете определить функцию обертки для IE6, например [Sarissa] (http : //dev.abiss.gr/sarissa/); взгляните на [Re-inventing XMLHttpRequest] (http://www.ilinsky.com/articles/XMLHttpRequest/), чтобы узнать, как это можно сделать (у меня нет времени сейчас). Вы [не можете расширять] (http://stackoverflow.com/questions/594428/how-can-i-add-properties-to-an-object-in-ie6/594460#594460) объект ActiveX, но вы может расширить вашу собственную функцию обертки, которая просто эмулирует необходимые свойства. Я думаю, что большинство библиотек проверит наличие 'window.XMLHttpRequest' и ваш объект-обертку. –

+0

Также обратите внимание, что IE8 в режиме совместимости с IE7 ≠ IE7.Я подозреваю, что объект XMLHttpRequest является одной из вещей, которые отличаются друг от друга: в IE7 это, по-видимому, всего лишь функция обертки над компонентом ActiveX, тогда как в IE8 она может быть реализована как «реальный» объект XHR. –

+1

В настоящее время не работает в FireFox. Ошибки XMLHttpRequest.open.apply – HMR

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

да, это в значительной степени то, что я делал в то время .. но IE6 - это то, что никто больше не должен поддерживать, тем более, что Microsoft сама перестала его поддерживать (расширением не поддерживающей XP) по состоянию на апрель 2014 года –

Смежные вопросы