एक पेज पर सभी AJAX अनुरोधों के लिए "हुक" जोड़ें


103

मैं जानना चाहता हूं कि क्या हर एक AJAX अनुरोध में "हुक" करना संभव है (या तो यह भेजे जाने के बारे में है, या घटनाओं पर) और एक कार्रवाई करें। इस बिंदु पर मैं मान रहा हूं कि पृष्ठ पर अन्य तृतीय-पक्ष स्क्रिप्ट हैं। इनमें से कुछ jQuery का उपयोग कर सकते हैं, जबकि अन्य नहीं करते हैं। क्या यह संभव है?


यह jQuery के साथ संभव है, इसलिए यह सादे पुराने जावास्क्रिप्ट के साथ संभव है, लेकिन आपको उनमें से प्रत्येक के लिए कम से कम 2 "हुक" की आवश्यकता होगी। वैसे भी, एक ही पृष्ठ पर दोनों का उपयोग क्यों करें?
योडा

2
कैसे इस पुस्तकालय का उपयोग करने के बारे में? github.com/slorber/ajax-interceptor
सेबेस्टियन लॉबर

यह एक अच्छा समाधान है: stackoverflow.com/questions/25335648/…
phazei

2
नोट: इस प्रश्न के उत्तर fetch()आधुनिक ब्राउज़र में अब नए एपीआई से किए गए अजाक्स कॉल को कवर नहीं करते हैं।
jfriend00

1
@ निर्वाण-मंगल - शायद यह: github.com/werk85/fetch-intercept/blob/develop/src/index.js
jfriend00

जवाबों:


109

एविव के जवाब से प्रेरित होकर , मैंने थोड़ी जांच-पड़ताल की और यही मैं सामने आया।
मुझे यकीन नहीं है कि स्क्रिप्ट में टिप्पणियों के अनुसार यह सब उपयोगी है और निश्चित रूप से केवल देशी 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
});

अनुरोध के बाद हुक का समर्थन करने के लिए इस प्रतिक्रिया का विस्तार करना अच्छा होगा
सेबस्टियन लॉबर

1
आपके कार्यान्वयन के आधार पर, मैंने एनपीएम पर कुछ प्रकाशित किया है जो अनुरोधों और प्रतिक्रियाओं दोनों के साथ काम करता है! github.com/slorber/ajax-interceptor
सेबेस्टियन लॉबर

4
कंसोल.लॉग (xhr.responseText) एक खाली स्ट्रिंग है क्योंकि उस समय xhr खाली होता है। यदि आप xhr वैरिएबल को ग्लोबल वैरिएबल में पास करते हैं और कुछ सेकंड देरी से सेट करते हैं, तो आप प्रॉपर्टीज को सीधे एक्सेस कर पाएंगे
टूलकिट

5
अच्छा उत्तर। यदि आप प्रतिक्रिया डेटा प्राप्त करना चाहते हैं, तो स्टेट बदलने पर रेडीस्टेट और स्थिति की जांच करें। xhr.onreadystatechange = function () {if (xhr.readyState == 4 && xhr.status == 200) {कंसोल.लॉग (JSON.parse (xhr.responseText)); }}
स्टेनली वांग

1
@ यूचेंग अगर हम xhr के onreadystatechange को जोड़ते हैं, तो क्या यह मूल तैयार राज्य परिवर्तन विधि को बेहतर तरीके से ओवरराइड करेगा, xhrObj.addEventListener ("लोड", fn) का बेहतर उपयोग करें
मोहम्मद हुसैन

126

नोट: स्वीकृत उत्तर वास्तविक प्रतिक्रिया नहीं देता है क्योंकि इसे बहुत जल्दी कहा जा रहा है।

आप ऐसा कर सकते हैं, जो विश्व स्तर पर किसी भी AJAX को उदारतापूर्वक रोक देगा और किसी भी कॉलबैक आदि को स्क्रू नहीं करेगा, जो शायद किसी भी तीसरे पक्ष 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)


धन्यवाद! Thats पूरी तरह से काम करता है। मैं केवल थोड़ा संशोधित करता हूं: यदि अनुरोध ठीक है, तो 404 this.statusइस मामले में सर्वर की स्थिति लौटाएं 200यदि तत्व नहीं मिला, 500, आदि। लेकिन कोड कोड, पूरी तरह से काम करता है।
MrMins

1
यह आपको पुराना लग सकता है लेकिन आप इसके लिए सभी प्यार के पात्र हैं। मैं गहराई से फंस गया था। बहुत बहुत धन्यवाद।
कारल्स अल्कोले

बस इसलिए कि मैंने इसके लिए थोड़ी खोज की है। "load"घटना केवल सफलता पर कहा जाता है। आप परिणाम के बारे में परवाह नहीं करते हैं (सिर्फ इतना है कि क्वेरी अंत किया था) का उपयोग कर सकते "loadend"घटना
Romuald ब्रुनेट

इसे खोजने में कई दिन लग गए। प्रतिभा के इस टुकड़े के लिए धन्यवाद।
डेविड

मैंने कई उत्तरों की कोशिश की है और यह WKWebView के साथ पूरी तरह से काम करता है। मुझे अजाक्स की घटनाओं का उपयोग करने में परेशानी हो रही थी क्योंकि jJascript को कॉल करने या addUserScript का उपयोग करने से पहले jQuery लोड नहीं किया जा सकता है। धन्यवाद!
जेक चेंग

21

चूँकि आप jquery का उल्लेख करते हैं, मुझे पता है कि jquery एक ऐसा .ajaxSetup()तरीका प्रदान करता है जो वैश्विक ajax विकल्प सेट करता है success, जिसमें इवेंट ट्रिगर्स जैसे शामिल हैं error, और beforeSend- जो कि आपको जो लग रहा है, वैसा ही लगता है।

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

निश्चित रूप से आपको इस समाधान का उपयोग करने का प्रयास करने वाले किसी भी पृष्ठ पर jQuery उपलब्धता को सत्यापित करने की आवश्यकता होगी।


1
सुझाव के लिए धन्यवाद, लेकिन यह दुर्भाग्य से AJAX कॉल को नहीं रोकता है जो AJAX का उपयोग नहीं कर रहे हैं।
यूलिया

8
खबरों में: एजेक्स द्वारा मारे गए यूनिकॉर्न कॉल जो AJAX का उपयोग नहीं कर रहे हैं
Dashu

3
वह AJAX वस्तु jquery का मतलब नहीं है। लेकिन फिर भी यू विल hv एक ही jquery उदाहरण का उपयोग करने के लिए हर समय
शिशिर अरोरा

1
बेहद मददगार। जोड़ना चाहते थे, एक और ट्रिगर स्टेटसकोड है। स्टेटसकोड जैसी किसी चीज़ में प्लग इन करके: {403: function () {एरर मेसो} आप एक एकल .axax रिक्वेस्ट को दोबारा लिखे बिना सभी ajax फ़ंक्शंस में एक वैश्विक वैश्विक / परमिट / रोल चेक प्रदान कर सकते हैं।
वाटरकैमैन

8

इसे करने की एक ट्रिक है।

चलने वाली सभी लिपियों से पहले, मूल XHMHttpReuqest ऑब्जेक्ट लें और इसे एक अलग संस्करण में सहेजें। फिर मूल XMLHttpRequest को ओवरराइड करें और सभी कॉल को अपनी वस्तु के माध्यम से निर्देशित करें।

Psuedo कोड:

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

10
यह उत्तर बिल्कुल सही नहीं है, यदि आप किसी वस्तु के प्रोटोटाइप को बदलते हैं तो भी सहेजे गए को बदल दिया जाएगा। साथ ही पूरे प्रोटोटाइप को एक फ़ंक्शन के साथ बदल दिया जा रहा है जो सभी ऐजैक्स अनुरोधों को तोड़ देगा। हालांकि इसने मुझे एक उत्तर देने की प्रेरणा दी।
9

8

मुझे जीथब पर एक अच्छी लाइब्रेरी मिली है जो अच्छी तरह से काम करती है, आपको इसे किसी भी अन्य जेएस फाइलों से पहले शामिल करना होगा

https://github.com/jpillora/xhook

यहाँ एक उदाहरण है जो किसी भी आने वाली प्रतिक्रिया में http हेडर जोड़ता है

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

2
महान एक! लेकिन एक क्रॉसवॉक नवीनतम क्रोम वेब-व्यू प्लगइन के साथ भी कॉर्डोवा आवेदन पर काम नहीं किया!
इस्लाम Attrash

1
यह मेरी विशेष जरूरतों के लिए पूरी तरह से काम करता है: वर्डप्रेस में, इवेंट्स ऑर्गनाइज़र प्लगइन फुल कैलेंडर से घटनाओं को फ़िल्टर करना
अल्फ्रेडो योंग

सभी अनुरोधों के लिए काम नहीं कर रहे हैं, कुछ लाने के लिए और xhr ठीक है, लेकिन उदाहरण के लिए यह Google recaptcha से xhr नहीं पकड़ता है
सर्जियो क्वेर्तो

@SergioQuintero: मुझे लगता है कि यह आपका GitHub मुद्दा है: github.com/jpillora/xhook/issues/102 । यहां अपनी टिप्पणी को हटाने पर विचार करें, क्योंकि यह पुस्तकालय के साथ कोई समस्या नहीं थी।
तीसवाँ

@SergioQuintero XHR इंटरफ़ेस का कोई भी ओवरराइड केवल उस दस्तावेज़ में होता है, न कि विश्व स्तर पर ब्राउज़र में क्योंकि यह एक बड़ी सुरक्षा / गोपनीयता छेद होगा। reCAPTCHA एक iframe में चलता है और आप वहां ओवरराइड नहीं चला सकते।
वाल्फ

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 अन्य पुस्तकालयों का उपयोग करके किए गए अनुरोधों को पकड़ नहीं पाएगा। उदाहरण के लिए एक्सटीजेएस। यदि आप केवल jQuery का उपयोग कर रहे हैं, तो यह एक अच्छा जवाब है। अन्यथा, यह हर समय काम नहीं करेगा।
नेपियन

1
अगर jquery का उदाहरण अलग है, तो यह jquery के अनुरोधों को भी पकड़ नहीं सकता है। यदि आवश्यक हो तो प्रोटोटाइप में बदलें
शिशिर अरोरा

3

Meouw के जवाब के अलावा, मुझे एक iframe में कोड इंजेक्ट करना था जो XHR कॉल स्वीकार करता है, और उपरोक्त उत्तर का उपयोग करता है। हालांकि, मुझे बदलना पड़ा

XMLHttpRequest.prototype.send = function(){

सेवा:

XMLHttpRequest.prototype.send = function(body)

और मुझे बदलना पड़ा

oldSend.apply(this, arguments);

सेवा:

oldSend.call(this, body);

IE8 दस्तावेज़ मोड के साथ IE9 में काम करने के लिए यह आवश्यक था । यदि यह संशोधन नहीं किया गया था, तो घटक ढांचे (विजुअल वेबजीयूआई) द्वारा उत्पन्न कुछ कॉल-बैक काम नहीं करते थे। इन लिंक पर अधिक जानकारी:

इन संशोधनों के बिना AJAX के पोस्टबैक समाप्त नहीं हुए।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.