2011-03-05 58 views
77

我想知道是否有可能「鉤住」每一個AJAX請求(無論是因爲它將要發送,還是事件)並執行一個操作。在這一點上,我假設頁面上還有其他第三方腳本。其中一些可能會使用jQuery,而另一些則不會。這可能嗎?爲頁面上的所有AJAX請求添加一個「鉤子」

+0

這是可能使用jQuery,因此有可能與普通的舊JavaScript,但需要有他們每個人至少2「掛鉤」。無論如何,爲什麼要在同一個頁面上使用兩個? – yoda

+2

如何使用此庫? https://github.com/slorber/ajax-interceptor –

+0

這是一個不錯的解決方案:http://stackoverflow.com/questions/25335648/how-to-intercept-all-ajax-requests-made-by-different- js-libraries – phazei

回答

89

aviv's answer的啓發,我做了一些調查,這就是我想出來的。
根據腳本中的註釋,我不確定它是否有用,當然只適用於使用本機XMLHttpRequest對象的瀏覽器。
我認爲它會工作,如果JavaScript庫正在使用,因爲他們將盡可能使用本機對象。

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

創意。 JS技巧再次挽救了這一天。 –

+0

這將是很好的擴展此響應以支持請求後鉤子 –

+1

根據您的實施,我已經發布了一些關於NPM的東西,可以同時處理請求和響應! https://開頭github上。com/slorber/ajax-interceptor –

9

有一個技巧來做到這一點。

在所有腳本運行之前,取原始的XHMHttpReuqest對象並將其保存在不同的var中。然後覆蓋原始的XMLHttpRequest並通過您自己的對象將所有調用指向它。

的僞代碼:

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

這個答案並不完全正確,如果你改變一個物體的原型,即使保存的物體也會改變。整個原型也被一個函數取代,這個函數將打破所有的Ajax請求。儘管如此,它的確激勵我提供了一個答案。 – meouw

19

既然你提到的jQuery,我知道jQuery提供一個.ajaxSetup()方法,設置全局AJAX選項,其中包括事件觸發像successerror,並beforeSend - 這是什麼聽起來像什麼你正在尋找。

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

當然,您需要在任何嘗試使用此解決方案的頁面上驗證jQuery可用性。

+1

感謝您的建議,但不幸的是,這不會攔截未使用​​AJAX的AJAX調用。 – Yuliy

+44

...閱讀您的評論.... – jondavidjohn

+5

在今天的消息:獨角獸殺死的AJAX調用沒有使用AJAX – Dashu

3

除了meouw的回答,我不得不將代碼注入攔截XHR調用的iframe,並使用了上面的答案。但是,我不得不改變

XMLHttpRequest.prototype.send = function(){ 

要:

XMLHttpRequest.prototype.send = function(arguments) 

我不得不改變

oldSend.apply(this, arguments); 

要:

oldSend.call(this, arguments); 

這是必須得到它的工作在IE9中用IE8文件m ode。如果未進行此修改,則組件框架(Visual WebGUI)生成的一些回調無效。在這些鏈接更多信息:

沒有進行這些修改AJAX回傳並沒有終止。

3

jquery ...

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

jQuery不會捕獲使用其他庫進行的請求。例如ExtJS。如果你只使用jQuery,這是一個很好的答案。否則,它不會一直工作。 – npiani

+0

它甚至不會抓住jquery請求,如果jQuery實例不同。如果需要,更改原型 –

4

使用的「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); 
    } 
}); 
67

結果。如果你沒有支持< = IE8可以做這將全面攔截任何 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); 
    }; 
})(); 

,你可以在這裏做與API的addEventListener這裏有些什麼更多的文檔:

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

+0

謝謝!那是完美的。 我只修改了一點:'this.status'在這種情況下返回服務器狀態'200',如果請求沒問題的話,404如果找不到元素,500等等。但是代碼很完美。 – MrMins

+0

這對你來說可能會感覺老舊,但你應該得到所有的愛。我深陷困境。謝謝一堆。 –

+0

只是因爲我爲此搜尋了一下。 ''load''事件只在成功時被調用。如果你不關心結果(只是查詢結束了),你可以使用「loadend」事件 –

4

我已經找到了一個好的圖書館在Github上,做的工作做好,你必須包括之前,任何其他js文件

https://github.com/jpillora/xhook

這裏要說的是增加了一個HTTP標頭的任何一個例子INCOM荷蘭國際集團響應

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

太棒了!但即使使用人行橫道最新的Chrome瀏覽器插件,也沒有在Cordova應用程序上工作! –

+0

這對我的特殊需求非常合適:在Wordpress中,從Events Organizer插件過濾事件 –

0

Ajax-hook是開源LIB鉤全球XMLHttpRequest對象,並更改默認Ajax請求和響應。 github上:https://github.com/wendux/Ajax-hook,例如:

hookAjax({ 

    //hook callbacks 
    onreadystatechange:function(xhr){ 
    console.log("onreadystatechange called: %O",xhr) 
    }, 

    onload:function(xhr){ 
    console.log("onload called: %O",xhr) 
    }, 

    //hook function 
    open:function(arg,xhr){ 
    console.log("open called: method:%s,url:%s,async:%s",arg[0],arg[1],arg[2]) 
    } 

}) 
相關問題