我想知道是否有可能“钩住”每个AJAX请求(即将发送或发生事件)并执行操作。此时,我假设页面上还有其他第三方脚本。其中一些可能使用jQuery,而其他一些则没有。这可能吗?
fetch()
现在在现代浏览器中通过较新的API 进行的Ajax调用。
我想知道是否有可能“钩住”每个AJAX请求(即将发送或发生事件)并执行操作。此时,我假设页面上还有其他第三方脚本。其中一些可能使用jQuery,而其他一些则没有。这可能吗?
fetch()
现在在现代浏览器中通过较新的API 进行的Ajax调用。
Answers:
受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);
}
}
}
// 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
});
注意:接受的答案不会产生实际的响应,因为调用时间太早。
您可以执行此操作,这通常会在全局范围内拦截任何 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做什么的更多文档:
(请注意,这不起作用== IE8)
this.status
在这种情况下,200
如果请求正常,则返回服务器状态;如果未找到该元素,则返回404;否则,返回500。
"load"
仅在成功时才调用该事件。如果你不关心结果(只是查询没有结束),您可以使用"loadend"
事件
既然你提到的jQuery,我知道jQuery提供了一个.ajaxSetup()
方法,其中包括事件触发的套装全局AJAX选项success
,error
以及beforeSend
-这是什么听起来像你在找什么。
$.ajaxSetup({
beforeSend: function() {
//do stuff before request fires
}
});
当然,您将需要在尝试使用此解决方案的任何页面上验证jQuery的可用性。
有一个技巧。
在运行所有脚本之前,请使用原始XHMHttpReuqest对象并将其保存在其他var中。然后覆盖原始XMLHttpRequest,并通过您自己的对象将所有调用定向到该对象。
伪代码:
var savd = XMLHttpRequest;
XMLHttpRequest.prototype = function() {
this.init = function() {
}; // your code
etc' etc'
};
我在Github上找到了一个很好的库,可以很好地完成工作,您必须在其他任何js文件之前添加它
https://github.com/jpillora/xhook
这是一个向任何传入响应添加http标头的示例
xhook.after(function(request, response) {
response.headers['Foo'] = 'Bar';
});
如果您想查看请求的结果,建议使用“ 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 );
}
});
jQuery的...
<script>
$(document).ajaxSuccess(
function(event, xhr, settings){
alert(xhr.responseText);
}
);
</script>
除了meouw的答案外,我还必须将代码注入到iframe中以拦截XHR调用,并使用上述答案。但是,我不得不改变
XMLHttpRequest.prototype.send = function(){
至:
XMLHttpRequest.prototype.send = function(body)
我不得不改变
oldSend.apply(this, arguments);
至:
oldSend.call(this, body);
要使其在IE9和IE8文档模式下工作,这是必需的。如果未进行此修改,则组件框架(Visual WebGUI)生成的某些回调将不起作用。这些链接的更多信息:
没有这些修改,AJAX回发不会终止。