通过上面的方法,我们可以拦截了 App 方法注册的一些全局方法,比如 onLaunch , onShow, onHide, 和Page 注册的事件如 onShow, onHide, onLoad, onPullDownRefresh, 等页面注册事件。
2.网络请求的监听
思路: 拦截微信的请求事件。
let Request = { request: function (e) { let success = e[0].success, fail = e[0].fail, beginTime = smaUtils.getTime(), endTime = 0 // 拦截请求成功方法 e[0].success = function () { endTime = smaUtils.getTime() const performance = { type: constMap.performance, event: eventMap.wxRequest, url: e[0].url, status: arguments[0].statusCode, begin: beginTime, end: endTime, total: endTime - beginTime } smaUtils.logInfo('success performance:', performance) // 这里做上报的事情 // SMA.performanceReport(performance) success && success.apply(this, [].slice.call(arguments)) } // 拦截请求失败方法 e[0].fail = function () { endTime = smaUtils.getTime() const performance = { type: constMap.performance, event: eventMap.wxRequest, url: e[0].url, status: arguments[0].statusCode, begin: beginTime, end: endTime, total: endTime - beginTime } smaUtils.logInfo('fail performance:', performance) // 这里做上报的事情 // SMA.performanceReport(performance) fail && fail.apply(this, [].slice.call(arguments)) } }, } // 替换微信相关属性 let oldWx = wx, newWx = {} for (var p in wx) { if (Request[p]) { let p2 = p.toString() newWx[p2] = function () { Request[p2](arguments) // 调用原来的wx.request 方法 oldWx[p2].apply(oldWx, [].slice.call(arguments)) } } else { newWx[p] = oldWx[p] } } // eslint-disable-next-line wx = newWx
疑惑:为什么要使用替换整个wx对象的方法呢? 不直接用我们的request 方法 替换 wx.request 方法
var oldRequest = wx.request wx.request = function(e) { // doSomething(); console.log('请求拦截操作...') oldRequest.call(this, e); // 调用老的request方法 } // 结果报错了: // TypeError: Cannot set property request of [object Object] which has only a getter
3.错误的监听
3.1 拦截App里注册的 onError事件
var oldAp = App App = function(options) { var oldOnError = options.onErrr options['onErrr'] = function(t) { // 做一些我们自己想做的事情 console.log('统计错误....', t) // 调用原来的onLaunch 方法 oldOnError.call(this, t) } // 调用原来的App 方法 oldApp(options) }
3.2 拦截 conole.error
console.error = function() { var e = [].slice.call(arguments) if (!e.length) { return true } const currRoute = smaUtils.getPagePath() // 统计错误事件 // SMA.errorReport({event: eventMap.onError, route: currRoute, errrMsg: arguments[0]}) smaUtils.logInfo('捕捉到error 事件,', e) oldError.apply(console, e) }
至此,我们已经有能力在小程序发起请求时,发生错误时,生命周期或者特殊函数回调时,我们都能在里面做一些我们想要的数据统计功能了。
说了这么多大家估计也看累了。鉴于篇幅,具体的代码就不在这里贴了。
最终实现的数据统计模块大致实现了以下功能:
普通埋点信息上报功能
错误信息上报功能
性能数据上报功能
具体的上报时机支持配置
支持指定网络环境上报
支持统计数据缓存到微信本地功能
整个统计代码的配置文件如下:
const wxaConfig = { project: 'myMiniProgram', // 项目名称 trackUrl: 'https://youhost.com/batch', // 后台数据统计接口 errorUrl: 'https://youhost.com/batch', // 后台错误上报接口 performanceUrl: 'https://youhost.com/batch', // 后台性能上报接口 version: '0.1', prefix: '_wxa_', priority: ['track', 'performance', 'error'], // 发送请求的优先级,发送时,会依次发送 useStorage: true, // 是否开启storage缓存 debug: false, // 是否开启调试(显示log) autoTrack: true, // 自动上报 onShow, onHide, 分享等 内置事件 errorReport: false, // 是否开启错误上报 performanceReport: false, // 接口性能上报 maxReportNum: 20, // 当次上报最大条数 intervalTime: 15, // 定时上报的时间间隔,单位 s, 仅当开启了定时上报有效。 networkList: ['wifi', '4g', '3g'], // 允许上报的网络环境 opportunity: 'pageHide' // pageHide、appHide、realTime(实时上报)、timing(定时上报) 上报的时机,四选一 } export default wxaConfig
具体上报时,上报的数据结构大致长这样:
项目已传到GitHub -> GitHub传送门-wxa