XMLHttpRequest如何拦截请求发送和结果获取?
我想在发送body参数前捕获到请求并更改body参数,并在得到返回结果的时候拦截做一层处理,请问如何实现?
回答:
很巧,我今年恰好解决了同样的问题。 我的场景是在不污染现有前端库的前提下,记录所有异步请求的耗时。 列出代码,仅供参考,完全能解决你的问题。不要被这么长的代码吓到,最核心的部分只有几行,大部分是我用来计算耗时用的。
(function(open, send) { window.timing = new Map();
var xhrOpenRequestUrl; // capture method and url
var xhrSendResponseUrl; // capture request body
var responseData; // captured response
XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
xhrOpenRequestUrl = new URL(url, document.location.href).href;
window.timing[xhrOpenRequestUrl] = {
begin: new Date().valueOf(),
method: method
}
open.apply(this, arguments);
};
XMLHttpRequest.prototype.send = function(data) {
this.addEventListener('readystatechange', function() {
var gaPageUrl=document.location.href;
var gaTitle=document.title;
if (window.timing[this.responseURL] && this.readyState === 4) {
xhrSendResponseUrl = this.responseURL;
var duration = new Date().valueOf() - window.timing[xhrSendResponseUrl].begin;
console.log({
hitType: 'timing',
timingCategory: gaTitle + "-" + document.location.href,
timingVar: window.timing[xhrSendResponseUrl].method + ':' + xhrSendResponseUrl ,
timingValue: duration,
timingLabel: JSON.stringify(data)
})
}
}, false);
send.apply(this, arguments);
}
})(XMLHttpRequest.prototype.open, XMLHttpRequest.prototype.send)
回答:
无法拦截。
JS 里内置的 API 除了 Proxy,压根也没提供 AOP(面向切面编程)的能力。
除非你复写它的原型链方法,但极不推荐此做法。因为如果你要做前端埋点或性能监控,你引入的那些库本身就会这么做(比如听云、OneAPM 之类的),你再做了二者就非常容易冲突,况且你复写的玩意儿大概率也不怎么健壮。
但你可以自己封装一层啊,封装层里你想怎么处理就怎么处理呗。需要 AJAX 的调用你自己封装的方法,而不是直接操作 XMLHttpRequest 对象。
P.S. 如果是开发 Chrome 插件那另有办法,但我估计你问的也不是怎么开发插件。
回答:
可以试试这个Ajax-hook
回答:
chrome中大部分api都是可以修改的,就比如你可以修改ajax的send方法,
let oldXHR = window.XMLHttpRequest;//hook xhr
function newXHR() {
let realXHR = new oldXHR();
let oldSendFun = realXHR.send;
//修改ajax的send方法
realXHR.send = function (body) {
console.log("拦截到消息提",body)
oldSendFun.call(realXHR,body)
}
return realXHR;
}
window.XMLHttpRequest = newXHR;
//这是一个测试用例
let ajax = new XMLHttpRequest();
ajax.open('post', 'inser.php', true);
ajax.send('name=2');
你也可以使用Proxy也可以做拦截,不过我还没试过。
既然说到拦截网络请求了,你也可以了解一下这个Service_Worker_API,虽然这个上手成本高,但是功能应该是最强到的,ajax,fetch,script脚本,css文件中的一些图片请求啥的都能拦截到也能做修改。
回答:
Service Worker 处理这种问题
回答:
'use strict';;(function () {
if (typeof window.XhrEvent === 'function') return false;
function XhrEvent (event, params) {
params = params || { bubbles: false, cancelable: false, detail: undefined };
var evt = document.createEvent('CustomEvent');
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
return evt;
}
XhrEvent.prototype = window.Event.prototype;
window.XhrEvent = XhrEvent;
})();
;(function () {
function xhrEventTrigger (event) {
// eslint-disable-next-line no-undef
var xhrEvent = new XhrEvent(event, { detail: this });
window.dispatchEvent(xhrEvent);
}
var oldXHR = window.XMLHttpRequest;
function newXHR (args) {
var realXHR = new oldXHR(args);
let oldSend = realXHR.send;
realXHR.send = function(data){
this.requestBody = data;
xhrEventTrigger.call(this, 'xhrSendStart');
oldSend.call(this, this.requestBody);
};
// 请求开始
realXHR.addEventListener('loadstart', function () { xhrEventTrigger.call(this, 'xhrLoadStart'); }, false);
// 请求进行中
realXHR.addEventListener('progress', function () { xhrEventTrigger.call(this, 'xhrProgress'); }, false);
realXHR.addEventListener('abort', function () { xhrEventTrigger.call(this, 'xhrAbort'); }, false);
// 请求错误
realXHR.addEventListener('error', function () { xhrEventTrigger.call(this, 'xhrError'); }, false);
// 请求中
realXHR.addEventListener('load', function () { xhrEventTrigger.call(this, 'xhrLoad'); }, false);
// 超时
realXHR.addEventListener('timeout', function () { xhrEventTrigger.call(this, 'xhrTimeout'); }, false);
// 请求完毕
realXHR.addEventListener('loadend', function () { xhrEventTrigger.call(this, 'xhrLoadEnd'); }, false);
// 请求状态改变
realXHR.addEventListener('readystatechange', function () { xhrEventTrigger.call(this, 'xhrReadyStateChange'); }, false);
return realXHR;
}
window.XMLHttpRequest = newXHR;
})();
window.addEventListener('xhrSendStart', function(e){ console.log(e.detail.requestBody);
e.detail.requestBody = '123321';
});
以上是 XMLHttpRequest如何拦截请求发送和结果获取? 的全部内容, 来源链接: utcz.com/p/936271.html