javascript 写一个ajax 自动拦截,并下载数据

Posted muamaker

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了javascript 写一个ajax 自动拦截,并下载数据相关的知识,希望对你有一定的参考价值。

<!DOCTYPE html>
<html lang="zh">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<title></title>
</head>
<body>
</body>
<script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
// 自动下载 ajax 的脚本
;(function($,flag,host)
	if(!flag)
		//如果关闭下载数据,则什么也不做,否则会拦截 ajax 请求返回的数据,进行下载
		return ;
	
	var ajax = $.ajax; //缓存原始的 ajax
	$.ajax = function(opt)
		var success =  opt.success || function();
		var url = opt.url || "";
		opt.success = function(res)
			try
				var name = url.split("?")[0];
				if(host)
					name = name.replace(host,"");
				
				name = name.replace(/\\//g,"_");
				downData(res,`$name.json`);
			catch(e)
				console.warn(e);
			
			success(res);
		
		return ajax(opt);
	
	function downData(data,name)
		if(typeof data == "object")
			data = JSON.stringify(data);
		
		var blob = new Blob([data], 
		  type: ‘text/html,charset=UTF-8‘   
		);
		window.URL = window.URL || window.webkitURL; 
		var a = document.createElement("a");
		a.setAttribute("download",name || "data.json");
		a.href = URL.createObjectURL(blob);
		a.click();
	
)($,true,"https://www.easy-mock.com");
 
//自动下载数据
$.ajax(
	url:"https://www.easy-mock.com/mock/5bb02bc0a0afc503f502a292/example/demo/secret",
	success(res)
		console.log(res);
	
)
</script>
</html>

  

使用原生的 xhr 和fetch 拦截

 

// 自动下载 ajax 的脚本
	// 命名空间
	window.ajax_interceptor_manny = 
		settings: 
			switchOn: false,
			switchQuery:false
		,
		originalXHR: window.XMLHttpRequest,
		myXHR: function() 
			console.log(" ---ajax 拦截--- ")
			let pageScriptEventDispatched = false;
			const modifyResponse = () => 
				//this.responseText = overrideTxt;
				//this.response = overrideTxt;
				if (pageScriptEventDispatched) 
					return;
				
				pageScriptEventDispatched = true;
				ajax_interceptor_manny.download(this.responseText, this.responseURL);
			

			// new 一个原生的 XMLHttpRequest 不需要参数,将 xhr 的属性,都复制给this,暴露到外面
			const xhr = new ajax_interceptor_manny.originalXHR();

			for (let attr in xhr) 
				if (attr === ‘onreadystatechange‘) 
					xhr.onreadystatechange = (...args) => 
						if (this.readyState == 4 && this.status == 200) 
							// 请求成功
							if (ajax_interceptor_manny.settings.switchOn) 
								// 开启拦截
								modifyResponse();
							
						
						this.onreadystatechange && this.onreadystatechange.apply(this, args);
					
					continue;
				 else if (attr === ‘onload‘) 
					xhr.onload = (...args) => 
						// 请求成功
						if (ajax_interceptor_manny.settings.switchOn) 
							// 开启拦截
							modifyResponse();
						
						this.onload && this.onload.apply(this, args);
					
					continue;
				 

				if (typeof xhr[attr] === ‘function‘) 
					this[attr] = xhr[attr].bind(xhr);
				 else 
					if (attr === ‘responseText‘ || attr === ‘response‘) 
						var k = "_"+attr;
						Object.defineProperty(this, attr, 
							get: () => this[k] == undefined ? xhr[attr] : this[k],
							set: (val) => this[k] = val,
						);
					 else 
						Object.defineProperty(this, attr, 
							get: () => xhr[attr],
							set: (val) => xhr[attr] = val,
						);
					
				
			
		,
		originalFetch: window.fetch.bind(window),
		myFetch: function(...args) 
			console.log(" ---fetch 拦截--- ")
			return ajax_interceptor_manny.originalFetch(...args).then((response) => 
				if (response.ok) 
					response.clone().text().then((res) => 
						ajax_interceptor_manny.download(res, response.url);
					).catch((e) => 
						console.warn(e)
					);
				
				return response;
			);
		,
		download(data, url) 
			try 
				if (ajax_interceptor_manny.settings.switchOn) 
					if (typeof data == "object") 
						data = JSON.stringify(data);
					
					var blob = new Blob([data], 
						type: ‘text/html,charset=UTF-8‘
					);
					window.URL = window.URL || window.webkitURL;

					var name = url;
					if(!(url.indexOf("http://") >= 0 || url.indexOf("https://") >= 0))
						//不存在域名
						url = window.origin + url; //手动添加一个,避免URL解析出错
					
					try 
						var u = new URL(url);
						name = u.pathname;
						if(ajax_interceptor_manny.settings.switchQuery)
							//需要带上 get 参数
							name = name + "$"+ u.search.replace("?","");
						
					 catch (e) 
					name = name.replace(new RegExp("//","g"),"/");
					name = name.replace(new RegExp("/","g"), "_");
					name = name + ".json";
					var a = document.createElement("a");
					a.setAttribute("download", name || "data.json");
					a.href = URL.createObjectURL(blob);
					a.click();
				
			 catch (e) 
				console.error("下载数据失败", e);
			

		,

		setSetting(data) 
			if (typeof data !== "object") 
				return;
			
			//设置环境
			for (var i in data) 
				ajax_interceptor_manny.settings[i] = data[i];
			
		,
		init() 
			window.XMLHttpRequest = ajax_interceptor_manny.myXHR;
			window.fetch = ajax_interceptor_manny.myFetch;
		
	
ajax_interceptor_manny.init();
ajax_interceptor_manny.setSetting(
	switchOn:true
);

  

 

还可以将这个拦截,写为一个浏览插件:

技术图片

 

插件代码地址: https://gitee.com/muand/ajaxDown/tree/master/ajaxDown

 

以上是关于javascript 写一个ajax 自动拦截,并下载数据的主要内容,如果未能解决你的问题,请参考以下文章

关于AJAX 第一篇

vue 封装axios 并省略写 dataparams参数

session过期,拦截ajax请求并跳转登录页面

判断一个请求是否为Ajax请求

Js 拦截全局ajax请求

SpringMVC-相关 Ajax及拦截器