listenutils
import $ from 'jquery';
// 获取地址参数
export const getUrlParmas = function (str) {
let res = {};
if (!str) return res;
let param = str.split("?")[1];
if (!param) return res;
let paramArr = param.split("&");
paramArr.forEach(item => {
const itemP = item.split("=");
res[itemP[0]] = itemP[1];
});
return res;
}
export const sendPb = function (url, data) {
if ('requestIdleCallback' in window) {
window.requestIdleCallback(() => sendPbRequest(url, data))
} else if(Promise && Promise.then) {
Promise.then(() => sendPbRequest(url, data))
}else{
sendPbRequest(url, data)
}
}
export const sendPbRequest = function (url, data) {
console.log("errorPb:触发" + JSON.stringify(data))
$.ajax({
url: url,
crossDomain: true,
dataType: 'json',
timeout: 10000,
type: 'POST',
data: JSON.stringify(data),
jsonp: 'callback',
success: function (result) {
},
error:function(err){
},
});
}
export const transPbData = function (data, config) {
if (!data) return {}
// const method = data.method.toUpperCase();
const body = data.body ? JSON.parse(data.body) : {}
const requestParams = Object.assign({}, getUrlParmas(data.orignUrl), body)
// 防止parse失败报错
const response = (data.response && data.response.indexOf(":") != -1) ? JSON.parse(data.response) : {}
// *** 默认先写山东青岛
// const partnerCodeC = requestParams.partnerCode || 'SD_CMCC_QD'
// const uuid = (config.uuidEnum && config.uuidEnum[partnerCodeC]) || ''
const uuid = ''
const type = (response.code && response.code != 'A000000') ? 1 : 0
return {
timestamp: new Date().getTime(),
message: response.message || '接口请求失败',
statusCode: data.status,
appVersion: config.appVersion,
hostIp: '', // 获取不到
partnerCode: config.pbPartnerCode,
mac: requestParams.mac || '',
uuid: uuid,
type: type,
ErrorCode: "E000007",
url: data.orignUrl,
body: data.body,
pingbackType: config.pingbackType,
appid: response.appId || requestParams.appId,
pageUrl: window.location.href
}
}
// 监听js报错
export const transJsErr = function (args, config) {
return {
timestamp: new Date().getTime(),
message: '代码报错',
statusCode: -1,
appVersion: config.appVersion,
hostIp: '', // 获取不到
partnerCode: config.pbPartnerCode,
mac: '',
uuid: '',
type: 0,
ErrorCode: "E000007",
url: args.filename,
pingbackType: config.pingbackType,
appid: '',
pageUrl: window.location.href
}
}
export const transFileErr = function (args, config) {
return {
timestamp: new Date().getTime(),
message: '文件访问失败',
statusCode: -1,
appVersion: config.appVersion,
hostIp: '', // 获取不到
partnerCode: config.pbPartnerCode,
mac: '',
uuid: '',
type: 0,
ErrorCode: "E000007",
url: args.target.src,
pingbackType: config.pingbackType,
appid: '',
pageUrl: window.location.href
}
}
listenXhr
import defaultxhrconfig from './xhrconfig';
import { getUrlParmas, sendPb,transJsErr,transPbData,transFileErr } from './listenUtils'
class listenXhr {
constructor(props) {
this.xhrconfig = props ? props : defaultxhrconfig
}
init() {
this.initCustom()
this.initXhr()
this.listenRequest()
this.listenErr()
this.listenFetch()
}
initCustom() {
if (typeof window.CustomEvent === "function") return false;
function CustomEvent(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;
}
CustomEvent.prototype = window.Event.prototype;
window.CustomEvent = CustomEvent;
}
initXhr() {
function ajaxEventTrigger(event) {
var ajaxEvent = new CustomEvent(event, { detail: this });
window.dispatchEvent(ajaxEvent);
}
var oldXHR = window.XMLHttpRequest;
function newXHR() {
var realXHR = new oldXHR();
realXHR.addEventListener('abort', function () { ajaxEventTrigger.call(this, 'ajaxAbort'); }, false);
realXHR.addEventListener('error', function () { ajaxEventTrigger.call(this, 'ajaxError'); }, false);
realXHR.addEventListener('load', function () { ajaxEventTrigger.call(this, 'ajaxLoad'); }, false);
realXHR.addEventListener('loadstart', function () { ajaxEventTrigger.call(this, 'ajaxLoadStart'); }, false);
realXHR.addEventListener('progress', function () { ajaxEventTrigger.call(this, 'ajaxProgress'); }, false);
realXHR.addEventListener('timeout', function () { ajaxEventTrigger.call(this, 'ajaxTimeout'); }, false);
realXHR.addEventListener('loadend', function () { ajaxEventTrigger.call(this, 'ajaxLoadEnd'); }, false);
realXHR.addEventListener('readystatechange', function () { ajaxEventTrigger.call(this, 'ajaxReadyStateChange'); }, false);
let send = realXHR.send;
realXHR.send = function (...arg) {
send.apply(realXHR, arg);
realXHR.body = arg[0];
ajaxEventTrigger.call(realXHR, 'ajaxSend');
}
let open = realXHR.open;
realXHR.open = function (...arg) {
open.apply(realXHR, arg)
realXHR.method = arg[0];
realXHR.orignUrl = arg[1];
realXHR.async = arg[2];
ajaxEventTrigger.call(realXHR, 'ajaxOpen');
}
let setRequestHeader = realXHR.setRequestHeader;
realXHR.requestHeader = {};
realXHR.setRequestHeader = function (name, value) {
realXHR.requestHeader[name] = value;
setRequestHeader.call(realXHR, name, value)
}
return realXHR;
}
window.XMLHttpRequest = newXHR;
}
// 监听fetch请求
listenFetch() {
if (!("fetch" in window)) {
return;
}
const that = this
const { fetch: originalFetch } = window;
window.fetch = async (...args) => {
let [resource, config] = args;
const response = await originalFetch(resource, config);
const errPbDomain = that.xhrconfig.errPbDomain
const pbDomain = that.xhrconfig.pbDomain
response
.clone()
.json()
.then((res) => {
// 有config的是请求接口
// 没有的是请求文件
if (config) {
// 不是pb的话
if (resource.indexOf(pbDomain) > -1) return
if (res && res.code != 'A000000') {
// 拼凑数据
config.orignUrl = resource
config.response = JSON.stringify(res)
const data = transPbData(config, that.xhrconfig)
sendPb(errPbDomain, data)
}
}
});
return response;
};
}
// 监听ajax请求
listenRequest() {
const that = this
window.addEventListener("ajaxReadyStateChange", function (e) {
let xhr = e.detail;
const errPbDomain = that.xhrconfig.errPbDomain
const pbDomain = that.xhrconfig.pbDomain
// readyState = 4 是请求完成
// 屏蔽pb
if (xhr.orignUrl && xhr.orignUrl.indexOf(pbDomain) > -1) return
if (xhr.readyState == 4 && xhr.orignUrl != errPbDomain) {
// xhr.getAllResponseHeaders() 响应头信息
// xhr.requestHeader 请求头信息
// xhr.responseURL 请求的地址
// xhr.responseText 响应内容
// xhr.orignUrl 请求的原始参数地址
// xhr.body post参数,(get参数在url上面)
// xhr.response 返回值
// pb请求数据
const data = transPbData(xhr, that.xhrconfig)
if (xhr.status == 200) {
let response = xhr.response
response = JSON.parse(response)
if (response && response.code != 'A000000') {
sendPb(errPbDomain, data);
}
} else {
sendPb(errPbDomain, data)
}
}
});
}
listenErr() {
const that = this
window.addEventListener(
"error",
(args) => {
const errPbDomain = that.xhrconfig.errPbDomain
// 代码报错
console.log('代码报错!!!!' + JSON.stringify(args));
if (args.filename) {
const data = transJsErr(args, that.xhrconfig)
sendPb(errPbDomain, data)
}
// 文件请求失败
if (args.target.tagName == "SCRIPT") {
const data = transFileErr(args, that.xhrconfig)
sendPb(errPbDomain, data)
}
// 图片加载错误
if(args.target.tagName === 'IMG'){
const data = transFileErr(args, that.xhrconfig)
sendPb(errPbDomain, data)
}
return true;
},
true
);
}
remove() {
window.addEventListener("ajaxReadyStateChange", () => { })
window.addEventListener("error", () => { })
}
}
export default listenXhr
config
import urlConfiger from "./urlConfiger";
// *** 需要配置
const errPbDomain = '';
// *** 需要配置
const appVersion = urlConfiger.getAppVersion()
// *** 需要配置
const pbPartnerCode = ''
// *** 需要配置
const pingbackType = ""
const pbDomain = ''
export default {
errPbDomain,
appVersion,
pbPartnerCode,
pingbackType,
pbDomain
}
new listenXhr() && new listenXhr().init()