为页面上的所有AJAX请求添加一个“钩子”

我想知道是否有可能“钩”到每一个AJAX请求(无论是因为它将要发送,或事件),并执行一个操作。 在这一点上,我假设页面上还有其他第三方脚本。 其中一些可能使用jQuery,而另一些则不可以。 这可能吗?

受到AVIV回答的启发,我做了一些调查,这就是我想出来的。
我不确定这是否是所有有用的脚本中的评论,当然只适用于使用本机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); } } } // eg 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 }); 

如果你不需要支持<= IE8,你可以这样做,它将全面拦截任何 AJAX,而不是搞乱任何可能由任何第三方AJAX库分配的callback等。 被接受的答案不会产生实际的答复,因为它被称为太早。

 (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

既然你提到了jquery,我知道jquery提供了一个.ajaxSetup()方法,它设置了全局的ajax选项,包括successerrorbeforeSend等事件触发器 – 这听起来就像你在找什么。

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

当然你需要在你试图使用这个解决scheme的页面上validationjQuery的可用性。

这是一个窍门。

在所有脚本运行之前,取原始的XHMHttpReuqest对象并将其保存在不同的var中。 然后覆盖原始的XMLHttpRequest,并通过你自己的对象来引导所有的调用。

伪代码:

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

如果您想查看请求的结果,使用“meouw”的答案,我build议使用以下解决scheme

 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 ); } }); 

我在Github上发现了一个很好的库,可以很好的完成这个工作,你必须把它包含在任何其他的js文件之前

https://github.com/jpillora/xhook

这里是一个添加一个http头到任何传入响应的例子

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

jQuery的…

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

除了meouw的回答,我不得不将代码注入拦截XHR调用的iframe,并使用上述的答案。 但是,我不得不改变

 XMLHttpRequest.prototype.send = function(){ 

至:

 XMLHttpRequest.prototype.send = function(arguments) 

而我必须改变

 oldSend.apply(this, arguments); 

至:

 oldSend.call(this, arguments); 

这是有必要得到它在IE9 文件模式与IE9的工作。 如果未进行此修改,组件框架(Visual WebGUI)生成的一些callback无效。 更多信息在这些链接:

  • Function.prototype.call
  • Function.prototype.apply的

没有这些修改AJAX回发没有终止。