페이지의 모든 AJAX 요청에 "후크"추가


102

모든 단일 AJAX 요청 (전송 될 때 또는 이벤트에 대해)에 "연결"하여 작업을 수행 할 수 있는지 알고 싶습니다. 이 시점에서 페이지에 다른 타사 스크립트가 있다고 가정합니다. 이들 중 일부는 jQuery를 사용하고 다른 일부는 사용하지 않을 수 있습니다. 이게 가능해?


jQuery로 가능합니다. 그래서 평범한 오래된 자바 스크립트로 가능합니다. 그러나 각각에 대해 적어도 2 개의 "후크"가 필요합니다. 어쨌든, 왜 같은 페이지에서 둘 다 사용합니까?
yoda 2011 년

2
이 라이브러리를 사용하는 것은 어떻습니까? github.com/slorber/ajax-interceptor
Sebastien Lorber

이것은 좋은 해결책입니다 : stackoverflow.com/questions/25335648/…
phazei

2
참고 :이 질문에 대한 답변은 fetch()현재 최신 브라우저 의 최신 API 에서 이루어진 Ajax 호출을 다루지 않습니다 .
jfriend00

1
@ 열반-MSU는 - 아마도 이것은 : github.com/werk85/fetch-intercept/blob/develop/src/index.js
jfriend00

답변:


109

aviv의 대답에 영감을 받아 약간 조사를했는데 이것이 제가 생각 해낸 것입니다. 스크립트의 주석에 따라
유용하다고할 수 없으며 물론 기본 XMLHttpRequest 객체를 사용하는 브라우저에서만 작동합니다 .
가능한 한 네이티브 개체를 사용하므로 자바 스크립트 라이브러리가 사용 중이면 작동한다고 생각합니다.

function addXMLRequestCallback(callback){
    var oldSend, i;
    if( XMLHttpRequest.callbacks ) {
        // we've already overridden send() so just add the callback
        XMLHttpRequest.callbacks.push( callback );
    } else {
        // create a callback queue
        XMLHttpRequest.callbacks = [callback];
        // store the native send()
        oldSend = XMLHttpRequest.prototype.send;
        // override the native send()
        XMLHttpRequest.prototype.send = function(){
            // process the callback queue
            // the xhr instance is passed into each callback but seems pretty useless
            // you can't tell what its destination is or call abort() without an error
            // so only really good for logging that a request has happened
            // I could be wrong, I hope so...
            // EDIT: I suppose you could override the onreadystatechange handler though
            for( i = 0; i < XMLHttpRequest.callbacks.length; i++ ) {
                XMLHttpRequest.callbacks[i]( this );
            }
            // call the native send()
            oldSend.apply(this, arguments);
        }
    }
}

// e.g.
addXMLRequestCallback( function( xhr ) {
    console.log( xhr.responseText ); // (an empty string)
});
addXMLRequestCallback( function( xhr ) {
    console.dir( xhr ); // have a look if there is anything useful here
});

지원 후 요청 후크에이 응답 확장 좋을 것이다
세바스티앙 Lorber

1
구현을 기반으로 요청과 응답 모두에서 작동하는 NPM에 무언가를 게시했습니다! github.com/slorber/ajax-interceptor
Sebastien Lorber

4
console.log (xhr.responseText)는 그 순간 xhr이 비어 있기 때문에 빈 문자열입니다. xhr 변수를 전역 변수에 전달하고 지연을 몇 초로 설정하면 속성에 직접 액세스 할 수 있습니다
Toolkit

5
좋은 대답입니다. 응답 데이터를 얻으려면 상태 변경시 readyState 및 상태를 확인하십시오. xhr.onreadystatechange = function () {if (xhr.readyState == 4 && xhr.status == 200) {console.log (JSON.parse (xhr.responseText)); }}
Stanley Wang

1
@ucheng 우리가 XHR의 onreadystatechange의를 추가하는 경우, 원래 준비 상태 변경 방법은 더 나은 xhrObj.addEventListener ( "로드", FN)를 사용하여보다 우선합니다
모하메드 후세인

125

참고 : 수락 된 답변은 너무 일찍 호출되기 때문에 실제 응답을 생성하지 않습니다.

이 작업을 수행 할 수있는 것입니다 일반적으로 절편 어떤 AJAX 세계적하지 망치 어떤 콜백 등 어쩌면 제 3 자 AJAX 라이브러리에 의해 할당 된 그.

(function() {
    var origOpen = XMLHttpRequest.prototype.open;
    XMLHttpRequest.prototype.open = function() {
        console.log('request started!');
        this.addEventListener('load', function() {
            console.log('request completed!');
            console.log(this.readyState); //will always be 4 (ajax is completed successfully)
            console.log(this.responseText); //whatever the response was
        });
        origOpen.apply(this, arguments);
    };
})();

여기에서 addEventListener API로 수행 할 수있는 작업에 대한 문서가 더 있습니다.

https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#Monitoring_progress

(이것은 작동하지 않습니다 <= IE8)


감사! 완벽하게 작동합니다. 나는 약간만 수정합니다. this.status이 경우 200요청이 OK이면 서버 상태를 반환하고 , 요소를 찾을 수 없으면 404, 500 등을 반환합니다. 그러나 코드는 완벽하게 작동합니다.
MrMins

1
이것은 당신에게 오래되었다고 느낄 수 있지만 당신은 이것에 대한 모든 사랑을받을 자격이 있습니다. 나는 깊이 갇혀 있었다. 무리 감사.
Carles Alcolea

단순히 내가 이것을 조금 검색했기 때문입니다. "load"이벤트는 성공이라고합니다. 당신은 당신이 사용할 수 있습니다 (쿼리가 종료 한 단지) 결과에 대해 걱정하지 않을 경우 "loadend"이벤트
로무 검은 머리

이것을 찾는 데 며칠이 걸렸습니다. 이 천재 조각에 감사드립니다.
David

나는 많은 답변을 시도했으며 이것은 WKWebView에서 완벽하게 작동합니다. 평가 자바 스크립트를 호출하거나 addUserScript를 사용하기 전에 jQuery가로드되지 않을 수 있기 때문에 Ajax 이벤트를 사용하는 데 문제가있었습니다. 감사합니다!
Jake Cheng

21

당신이 jQuery를 언급 이후, 나는 JQuery와 이벤트에게 알고있는 .ajaxSetup()방법을 같은 이벤트 트리거를 포함 세트 글로벌 아약스 옵션 success, error그리고 beforeSend- 당신이 찾고있는 것 같은데 어떤이다.

$.ajaxSetup({
    beforeSend: function() {
        //do stuff before request fires
    }
});

물론이 솔루션을 사용하려는 모든 페이지에서 jQuery 가용성을 확인해야합니다.


1
제안 해 주셔서 감사합니다.하지만 이것은 AJAX를 사용하지 않는 AJAX 호출을 가로 채지 않습니다.
Yuliy 2011 년

8
오늘 뉴스에서 : 유니콘은 AJAX를 사용하지 완료 AJAX 호출에 의해 살해
Dashu

3
그는 jquery AJAX 객체를 의미하지 않습니다. 하지만 그래도 매번 동일한 jquery 인스턴스를 사용할 수 있습니다
Shishir Arora

1
매우 도움이됩니다. 추가하고 싶은 또 다른 트리거는 statusCode입니다. statusCode : {403 : function () {error msg}와 같은 것을 연결하면 단일 .ajax 요청을 다시 작성하지 않고도 모든 ajax 함수에 대한 전역 auth / perms / role 검사를 제공 할 수 있습니다.
Watercayman

8

그것을 수행하는 트릭이 있습니다.

모든 스크립트를 실행하기 전에 원본 XHMHttpReuqest 개체를 가져 와서 다른 var에 저장합니다. 그런 다음 원래 XMLHttpRequest를 재정의하고 자체 개체를 통해 모든 호출을 전달합니다.

의사 코드 :

 var savd = XMLHttpRequest;
 XMLHttpRequest.prototype = function() {
         this.init = function() {
         }; // your code
         etc' etc'
 };

10
이 대답은 정답이 아닙니다. 객체의 프로토 타입을 변경하면 저장된 객체도 변경됩니다. 또한 전체 프로토 타입은 모든 ajax 요청을 중단하는 하나의 함수로 대체되고 있습니다. 그래도 대답을 제공하도록 영감을 얻었습니다.
meouw 2011 년

8

Github에서 작업을 잘 수행하는 좋은 라이브러리를 찾았습니다. 다른 js 파일보다 먼저 포함해야합니다.

https://github.com/jpillora/xhook

다음은 수신 응답에 http 헤더를 추가하는 예입니다.

xhook.after(function(request, response) {
  response.headers['Foo'] = 'Bar';
});

2
훌륭합니다! 그러나 횡단 보도 최신 크롬 웹보기 플러그인을 사용하더라도 Cordova 응용 프로그램에서 작동하지 않았습니다!
이슬람 Attrash

1
이것은 내 특정 요구에 완벽하게 작동했습니다. Wordpress에서 Events Organizer 플러그인 전체 일정의 이벤트 필터링
Alfredo Yong

모든 요청, 일부 가져 오기 및 xhr에 대해 작동하지 않지만 예를 들어 Google recaptcha에서 xhr을 잡지 않습니다
Sergio Quintero

@SergioQuintero : 이것이 GitHub 문제라고 가정합니다 : github.com/jpillora/xhook/issues/102 . 라이브러리에 문제가 아니므로 여기에서 댓글을 삭제하는 것이 좋습니다.
thirtydot

@SergioQuintero XHR 인터페이스의 모든 재정의는 해당 문서에서만 발생하며 브라우저에서는 전역 적으로 발생하지 않습니다. 이는 엄청난 보안 / 개인 정보 보호 구멍이되기 때문입니다. reCAPTCHA는 iframe에서 실행되며 거기에서 재정의를 실행할 수 없습니다.
Walf

5

"meouw"의 대답을 사용하여 요청 결과를 보려면 다음 솔루션을 사용하는 것이 좋습니다.

function addXMLRequestCallback(callback) {
    var oldSend, i;
    if( XMLHttpRequest.callbacks ) {
        // we've already overridden send() so just add the callback
        XMLHttpRequest.callbacks.push( callback );
    } else {
        // create a callback queue
        XMLHttpRequest.callbacks = [callback];
        // store the native send()
        oldSend = XMLHttpRequest.prototype.send;
        // override the native send()
        XMLHttpRequest.prototype.send = function() {
            // call the native send()
            oldSend.apply(this, arguments);

            this.onreadystatechange = function ( progress ) {
               for( i = 0; i < XMLHttpRequest.callbacks.length; i++ ) {
                    XMLHttpRequest.callbacks[i]( progress );
                }
            };       
        }
    }
}

addXMLRequestCallback( function( progress ) {
    if (typeof progress.srcElement.responseText != 'undefined' &&                        progress.srcElement.responseText != '') {
        console.log( progress.srcElement.responseText.length );
    }
});

3

jquery ...

<script>
   $(document).ajaxSuccess(
        function(event, xhr, settings){ 
          alert(xhr.responseText);
        }
   );
</script>

1
jQuery는 다른 라이브러리를 사용하여 만든 요청을 포착하지 않습니다. 예를 들어 ExtJS. jQuery 만 사용하는 경우 좋은 대답입니다. 그렇지 않으면 항상 작동하지 않습니다.
npiani 2014 년

1
jquery 인스턴스가 다른 경우 jquery 요청도 포착하지 않습니다. 필요한 경우 protype에서 변경
Shishir 아 로라에게

3

meouw의 답변 외에도 XHR 호출을 가로채는 iframe에 코드를 삽입하고 위의 답변을 사용했습니다. 그러나 나는 변해야했다

XMLHttpRequest.prototype.send = function(){

에:

XMLHttpRequest.prototype.send = function(body)

그리고 나는 변해야했다

oldSend.apply(this, arguments);

에:

oldSend.call(this, body);

이것은 IE8 문서 모드 로 IE9에서 작동하도록하기 위해 필요했습니다 . 이 수정이 이루어지지 않은 경우 구성 요소 프레임 워크 (Visual WebGUI)에서 생성 된 일부 콜백이 작동하지 않았습니다. 다음 링크에서 추가 정보 :

이러한 수정 없이는 AJAX 포스트 백이 종료되지 않았습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.