JavaScript가 AJAX 이벤트를 감지합니다.


78

좋아, 그래서 기본적으로 페이지에 약간의 자바 스크립트를 갖고 싶어서 어떻게 든 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 프레임 워크를 사용하는지 또는 프레임 워크를 사용하지 않더라도 트리거하도록이 리스너를 확장 할 수 있기를 원합니다. 그래서한다면 예를 들어 도 한 페이지에 (W3 스쿨에서 일반적인 Ajax 코드) 다음 코드를 :

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 "global event listener"코드는 해당 호출을 감지하지 못했습니다.

좀 더 파헤 쳤고 기본적으로 개체를 임시 개체에 저장하고 지정된 함수를 호출 한 다음 임시 함수를 호출하는 "래퍼"개체로 현재 개체를 덮어 쓸 수 있다는 것을 알고 있습니다. 원래 객체가 생성 / 사용되는 시간. 하지만 항상 미리 알지는 못합니다 ...

그래서 ...이게 가능합니까? 일반 객체 또는 xyz 프레임 워크에서 수행되었는지 여부에 관계없이 ajax get / post 요청이 만들어 졌는지 감지하는 방법이 있습니까? 아니면 각 프레임 워크를 처리하기 위해 중복 코드를 만들고 미리 생성 / 사용되는 ajax 객체를 알아야합니까?

편집하다:

요청이 발생했음을 감지하는 것만으로는 충분하지 않다는 것을 잊었습니다. 또한 요청에서 전송되는 데이터를 캡처해야합니다. 아래 설명에 제공된 링크는 "a"요청이 이루어 졌는지 확인하는 데 도움이되지만 데이터가 전송되지는 않습니다. 추신-아래 링크에 제공된 답변은 적어도 어쨌든 나에게는 명확하지 않습니다.



링크 주셔서 감사합니다! 이 질문은 전적으로 그 질문과 같지 않습니다. 요청에서 전송되는 데이터를 캡처 할 수 있어야했기 때문입니다. 그러나 그것은 나를 올바른 길로 인도했고 해결책을 찾았다 고 생각하며 테스트가 완료되면 게시 할 것입니다. 감사!
— 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>

지도:

이것을 페이지에 c / p하거나 .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에 관심이 없다면 현재 상태로 내 솔루션을 게시하기로 결정했습니다.

나는 이것을 (이 게시 날짜 현재) 에서 테스트했습니다 : Current Safari, Current Chrome, Current FireFox, IE8, IE8 (IE7 호환 가능). IE6은 ActiveX 객체를 사용하고 거의 모든 것이 XMLHttpRequest를 사용하기 때문에 현재 IE6에서는 작동하지 않습니다.

지금은 기본적으로 프로토 타입 / 확장 / 오버로드 (?) ActiveXObject ( "Microsoft.XMLHTTP") 방법에 대한 단서가 없습니다. 이것이 제가 현재 연구하고있는 것입니다.

위에서 테스트 한 각 브라우저에서 이것은 일반 객체와 jquery 및 프로토 타입 프레임 워크의 AJAX 요청과 함께 작동합니다. 나는 거기에 다른 프레임 워크가 있다는 것을 알고 있지만 IMO이 두 가지가 주요 프레임 워크입니다. MooTools를 QA 할 수도 있지만 그 외에는 테스트 만해도 괜찮습니다.

누구나 다른 브라우저 및 / 또는 프레임 워크에 대한 결과를 테스트하고 게시하여 기여하고 싶다면 감사하겠습니다. :)


1
Sarissa 처럼 IE6에 대한 래퍼 함수를 ​​정의 할 수 있습니다 . 한 번 봐 가지고 다시 발명 XMLHttpRequest의 이은 (지금은 시간이 없어) 할 수있는 방법을 볼 수 있습니다. 당신은 확장 할 수 없습니다 ActiveX 객체를,하지만 당신은 단순히 필요한 속성을 에뮬레이트 자신의 래퍼 기능을 확장 할 수 있습니다. 대부분의 라이브러리가 존재하는지 테스트 window.XMLHttpRequest하고 래퍼 개체가 감지 될 것이라고 생각합니다.
— Marcel Korpel 2010 년

또한 IE7 호환 모드의 IE8 ≠ IE7에 유의하십시오. XMLHttpRequest개체가 다른 것 중 하나 라고 생각합니다 . IE7에서는 ActiveX 구성 요소에 대한 래퍼 함수 인 것처럼 보이지만 IE8에서는 '실제'XHR 개체로 구현 될 수 있습니다.
— Marcel Korpel 2010 년

1
현재 FireFox에서는 작동하지 않습니다. XMLHttpRequest.open.apply 오류 출력
— HMR 2014

여전히 잘 작동하지만, 어떤 이유로 XMLHttpRequest.send크롬에서 모든 클릭에 호출되고, 콜백 클릭이 발생할 때마다 실행되는 끝
— 페트르 Gazarov

@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 4 월 2014 년으로 뭔가 아무도 더 이상 지원되지 않아야 특히 마이크로 소프트 이후 자체가 (XP를 지원하지 않는 확장자)을 지원하는 정지
— 크레용 폭력
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.