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.