/**
* xhr_proxy.js
* 通过劫持原生XMLHttpRequest实现对页面ajax请求的监听
* @author binaryfire
*/
const READY_STATE_CHANGE = 'readystatechange';
let gHandlerList = [],//截获请求的处理函数列表
gIsInited = false;//是否已经初始化
let T_RSC_HANDLERS = Symbol('readyStateChangeHandler');
let initProxy = function(){
if(gIsInited)return;
gIsInited = true;
 
//这里先缓存一份原生的XMLHttpRequest类
let winXMLHttpRequest = window.XMLHttpRequest;
 
//用于替换原生XMLHttpRequest的类,继承自XMLHttpRequest
let ProxyXHR = class extends winXMLHttpRequest{
constructor(){
super(...arguments);
//readystatechange
//数组中第0个为页面中调用xhr.onreadystatechange的回调函数
//其他的为页面中调用addEventListener('readystatechange')时的回调函数
this[T_RSC_HANDLERS] = [null];
//调用原生XMLHttpRequest的addEventListener,添加对readystatechange事件的监听
super.addEventListener(READY_STATE_CHANGE,async ()=>{
if(this.readyState == 4 && gHandlerList.length){//只有4的时候会回调proxyHandler
try{
//调用注册的handler
await gHandlerList.map(proxyHandler => proxyHandler.call(this,this));
}
catch(e){
//TODO 这里可以替换为其他的错误处理逻辑
console.error(e);
}
}
//调用页面中注册的回调函数,保证页面中逻辑正常
this[T_RSC_HANDLERS].forEach(handler => handler && handler.apply(this,arguments));
});
}
/**
* 重写addEventListener函数,对readystatechange事件做特殊处理
*/
addEventListener(type,handler){
if(type == READY_STATE_CHANGE){
this[T_RSC_HANDLERS].push(handler);
}
else{
return super.addEventListener(...arguments);
}
}
/**
* 重写removeEventListener函数,对readystatechange事件做特殊处理
*/
removeEventListener(type,handler){
if(type == READY_STATE_CHANGE){
this[T_RSC_HANDLERS] = this[T_RSC_HANDLERS].filter(i => i!== handler);
}
else{
return super.removeEventListener(...arguments);
}
}
/**
* 重写onreadystatechange属性的setter
*/
set onreadystatechange(val){
this[T_RSC_HANDLERS][0] = val;
}
/**
* 重写onreadystatechange属性的getter
*/
get onreadystatechange(){
return this[T_RSC_HANDLERS][0] || null;
}
 
}
//覆盖原生的XMLHttpRequest
window.XMLHttpRequest = ProxyXHR;
}
 
/**
* 增加一个handler
* 当xhr.readyState == 4时,回调handler,handler中,可以通过xhr.responseText获取请求返回内容
* @param {function} handler function(xhr){}
*/
let addHandler = function(handler){
initProxy();
gHandlerList.push(handler);
}
/**
* 移除指定的handler
* @param {function} handler 调用addHandler时添加的handler
*/
let removeHandler = function(handler){
gHandlerList = gHandlerList.filter(h => h!== handler);
}
module.exports.addHandler = addHandler;
module.exports.removeHandler = removeHandler;
 
 
<webview id="foo" src="https://wx.qq.com/" preload="./preload.js" nodeintegration allowpopups disablewebsecurity style="min-width:640px; min-height:1000px"></webview>
 
/**
* preload.js
*/
const xhrProxy = require('./xhr_proxy.js');
const {ipcRenderer} = require('electron');
xhrProxy.addHandler(function(xhr){
let data = {};
//TODO 具体业务代码
console.log(xhr.responseText)
 
//通过ipcRenderer.sendToHost即可将xhr内容发送到BrowserWindow中
ipcRenderer.sendToHost('channel',data);
});
 

自定义xmlhttprequest的更多相关文章

  1. Laravel 5.5 FormRequest 自定义错误消息 postman调试时X-Requested-With设为XMLHttpRequest

    Laravel 5.5 FormRequest 自定义错误消息 使用FormRequest进行表单验证,就不用让验证逻辑和控制器里面的逻辑都混在一起.但在使用的时候呢,发现json错误返回的数据,与我 ...

  2. ASP.NET Core中显示自定义错误页面

    在 ASP.NET Core 中,默认情况下当发生500或404错误时,只返回http状态码,不返回任何内容,页面一片空白. 如果在 Startup.cs 的 Configure() 中加上 app. ...

  3. ASP.NET MVC自定义验证Authorize Attribute

    前几天Insus.NET有在数据库实现过对某一字段进行加密码与解密<使用EncryptByPassPhrase和DecryptByPassPhrase对MS SQLServer某一字段时行加密和 ...

  4. XMLHttpRequest对象用法

    xmlhttprequest is what? 用户后台与服务器交换数据. 可以在不重新加载页面的情况下更新网页: 在页面已加载后从服务器请求数据: 在页面已加载后从服务器接收数据: 在后台向服务器发 ...

  5. DataTables 自定义

    自定义取的参数方法 getQueryCondition = function(data) { var param = {}; ]) { param.order =data.columns[data.o ...

  6. Struts2 自定义拦截器

    自定义拦截器(权限管理),包含了对ajax和表单请求的拦截 package com.interceptor; import java.io.IOException; import java.io.Pr ...

  7. 百度地图API 海量点 自定义添加信息

    <!--添加百度地图--> <script type="text/javascript" src="http://api.map.baidu.com/a ...

  8. XMLHttpRequest的跨域请求

    缘起 由于浏览器的同源策略,非同源不可请求. 但是,在实践当中,经常会出现需要跨域请求资源的情况,比较典型的例如某个子域名向负责进行用户验证的子域名请求用户信息等应用. 以前要实现跨域访问,可以通过J ...

  9. HTTP脚本化——XMLHttpRequest对象的学习笔记

    一. HTTP 请求和响应 一个HTTP请求由4部分组成 HTTP请求方法(也叫动作Verb) 正在请求的URL 一个可选的请求头集合(可能包含身份验证信息等) 一个可选的请求主体 服务器返回的HTT ...

随机推荐

  1. 箭头函数 与 forEach

    array.forEach(function(item,index){ }.bind(this)); 同 array.forEach((item,index) =>{ });

  2. C++-POJ2503-Babelfish[hash]

    哈个希加挂个链表 一个要背的字符串hash函数ELFhash() mod数取数据最大容量的1.5倍最佳?! #include <set> #include <map> #inc ...

  3. 关于MySQL的tinyint(3)问题

    mysql 中int(1)和tinyint(1)中的1只是指定显示长度,并不表示存储长度.tinyint可以存储1字节, 即unsigned 0~255(signed -127~127).显示大小不受 ...

  4. vue中mixins的理解及应用

    vue中mixins的理解及应用 vue中提供了一种混合机制--mixins,用来更高效的实现组件内容的复用.最开始我一度认为这个和组件好像没啥区别..后来发现错了.下面我们来看看mixins和普通情 ...

  5. 每天进步一点点------Allegro 修线

    Allegro中修线的方法有很多种,这里重点介绍走线的移动和走线的替换,掌握这两种方法,基本可以完成电路板的修线工作.  走线的移动 第1步:执行菜单命令Route->Slide,进入移动走线命 ...

  6. 【原】AMFObject数据格式详解

    AMF AMF是Action Message Format(动作消息格式)的简写,它是一种二进制的数据格式.它的设计是为了把actionscript里面的数据(包括Object, Array, Boo ...

  7. java中的try-catch-finally中的return的执行顺序

    在这里看到了try catch finally块中含有return语句时程序执行的几种情况,但其实总结的并不全,而且分析的比较含糊.但有一点是可以肯定的,finally块中的内容会先于try中的ret ...

  8. windows10桌面突然变灰了

    不靠谱的第三方软件重装系统,装了以后系统有点问题,会隔一段时间变灰 了 windows+ctrl+c 直接就恢复色彩了

  9. extern "C" 与函数重载

    前言 如果向要在一个文件中使用另一个文件中的变量,不能在头文件中定义全局变量,因为被多个文件包含后会导致编译出错,并且静态的static变量,只能在本文件内使用,这时候就可以使用extern关键字. ...

  10. kali 安装与配置

    打开虚拟机 新建一个虚拟机 导入虚拟文件 然后进行下面的步骤 开启虚拟机 语言:中文简体 地区: 中国 语言: 汉语 自动安装 配置网络 配置域名 填写密码(两次一致) 自动校对时钟 使用整个磁盘 选 ...