国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 課堂 > 小程序 > 正文

微信小程序數(shù)據(jù)統(tǒng)計(jì)和錯(cuò)誤統(tǒng)計(jì)的實(shí)現(xiàn)方法

2020-03-21 15:53:18
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

某些情況下我們需要對(duì)小程序某些用戶的行為進(jìn)行數(shù)據(jù)進(jìn)行統(tǒng)計(jì),比如統(tǒng)計(jì)某個(gè)頁(yè)面的UV, PV等,統(tǒng)計(jì)某個(gè)功能的使用情況等。好讓產(chǎn)品對(duì)于產(chǎn)品的整個(gè)功能有所了解。 在網(wǎng)頁(yè)里,我們很多人都用過(guò)谷歌統(tǒng)計(jì),小程序里也有一些第三方數(shù)據(jù)統(tǒng)計(jì)的庫(kù), 比如騰訊的MTA等等。 但是,第三方的數(shù)據(jù)統(tǒng)計(jì)庫(kù)要么功能太簡(jiǎn)單,滿足不了需求,要么就是要收費(fèi)。(留下了貧窮的淚水。) 等等,又不是你出錢,怕啥? 貴一點(diǎn)就貴一點(diǎn)呀。

嗯,說(shuō)的沒(méi)錯(cuò)。但是,公司團(tuán)隊(duì)內(nèi)部想實(shí)現(xiàn)一套完整的自己的數(shù)據(jù)統(tǒng)計(jì)系統(tǒng)以滿足自己的需求。所以,還是沒(méi)有用第三方的。

所以,具體要統(tǒng)計(jì)些啥?

產(chǎn)品經(jīng)理

  • 想知道用戶都是怎么進(jìn)入我們的小程序的?
  • 用戶在我們小程序里那個(gè)頁(yè)面停留的時(shí)間最長(zhǎng)?平均用戶停留時(shí)間是多少?
  • 想知道我們最近開(kāi)發(fā)的那個(gè)功能用的人多不多?
  • 想統(tǒng)計(jì)小程序里的一些按鈕有多少用戶點(diǎn)擊了

開(kāi)發(fā)自己

  • 總是很難復(fù)現(xiàn)用戶端出現(xiàn)的bug,
  • 要是可以知道用戶端發(fā)生錯(cuò)誤時(shí),知道用戶當(dāng)時(shí)的用的手機(jī)型號(hào),微信版本,網(wǎng)絡(luò)環(huán)境,頁(yè)面參數(shù),和錯(cuò)誤信息就好了
  • 想知道我們小程序啟動(dòng)時(shí)間是多少?
  • 接口在用戶端的平均響應(yīng)時(shí)間是多少ms? 哪些接口報(bào)錯(cuò)了

針對(duì)產(chǎn)品經(jīng)理的需求,我們可以知道,Ta想要的是就是數(shù)據(jù)統(tǒng)計(jì)要實(shí)現(xiàn)的功能。對(duì)于開(kāi)發(fā)來(lái)說(shuō),我們關(guān)注的更多就是錯(cuò)誤統(tǒng)小程序性能這塊的東西。

好,到這里,我們需求是明白了。就是要實(shí)現(xiàn)一套既能統(tǒng)計(jì)普通的埋點(diǎn)數(shù)據(jù),也要能統(tǒng)計(jì)到小程序里一些特殊觸發(fā)的事件,比如appLaunch, appHide 等,還要可以統(tǒng)計(jì)錯(cuò)誤。

好,那先來(lái)看看如何實(shí)現(xiàn)產(chǎn)品的需求吧

用戶進(jìn)入小程序可以在 小程序 onLaunch 回調(diào)里拿到參數(shù) 的scene 值,這樣就可以知道用戶是怎么進(jìn)入小程序的了。小case, 難不到我。

嗯,第一個(gè)需求實(shí)現(xiàn)了,那如何統(tǒng)計(jì)第二個(gè)呢?如何統(tǒng)計(jì)某個(gè)頁(yè)面的停留時(shí)間呢?

這也難不倒我,用戶在進(jìn)入頁(yè)面時(shí)會(huì)觸發(fā)onShow 事件, 同樣,在離開(kāi)頁(yè)面(或者切后臺(tái)時(shí))會(huì)觸發(fā)onHide事件,我只需要在onShow里記錄一下時(shí)間,同時(shí)在onHide 里也記錄一下時(shí)間,把兩個(gè)時(shí)間一減就可以了。

Page({    data: {    beginTime: 0,    endTime: 0    },    onShow: function() {     // Do something when page show.     this.setData({      beginTime: new Date().getTime()     })    },    onHide: function() {     // Do something when page hide.     let stayTime = new Date().getTime() - this.beginTime;     // 這個(gè)就是用戶在這個(gè)頁(yè)面的停留時(shí)間了    },  })

等等,這樣確實(shí)實(shí)現(xiàn)了需求,萬(wàn)一產(chǎn)品要統(tǒng)計(jì)所有也面的停留時(shí)長(zhǎng)? 那我們豈不要在每一個(gè)頁(yè)面都這樣寫一遍?有沒(méi)有更好的方法呢?

好,接下來(lái)就是數(shù)據(jù)統(tǒng)計(jì)實(shí)現(xiàn)的要點(diǎn)了,即攔截微信原生事件,這樣可以在某個(gè)特殊事件觸發(fā)時(shí),做一些我們統(tǒng)計(jì)的事情。同時(shí),還要攔截微信發(fā)生網(wǎng)絡(luò)請(qǐng)求的方法,這樣可以拿到網(wǎng)絡(luò)請(qǐng)求相關(guān)的數(shù)據(jù),最后,為了能統(tǒng)計(jì)到錯(cuò)誤,還需要攔截微信發(fā)生錯(cuò)誤的方法。

1.特殊事件的監(jiān)聽(tīng)

App(Object object)

注冊(cè)小程序。接受一個(gè) Object 參數(shù),其指定小程序的生命周期回調(diào)等。

App() 必須在 app.js 中調(diào)用,必須調(diào)用且只能調(diào)用一次。不然會(huì)出現(xiàn)無(wú)法預(yù)期的后果。

  • 攔截全局的事件:
  • 下面是小程序官方文檔對(duì)于App 注冊(cè)方法的文檔:
App({ onLaunch (options) {  // Do something initial when launch. }, onShow (options) {  // Do something when show. }, onHide () {  // Do something when hide. }, onError (msg) {  console.log(msg) }, globalData: 'I am global data'}) 

假如我們要在小程序onLaunch 時(shí)打印一句hello Word,我們有哪些方法實(shí)現(xiàn)?

方法1:

直接寫在onLaunch方法里

onLaunch (options) {   console.log('hello World') }

方法2:

使用 monkey patch方法 猴子補(bǔ)丁(monkey patch)

猴子補(bǔ)丁主要有以下幾個(gè)用處:

  1. 在運(yùn)行時(shí)替換方法、屬性等
  2. 在不修改第三方代碼的情況下增加原來(lái)不支持的功能
  3. 在運(yùn)行時(shí)為內(nèi)存中的對(duì)象增加patch而不是在磁盤的源代碼中增加

舉個(gè)栗子,假如我們?cè)赾onsole.log 方法里都先打印出當(dāng)前的時(shí)間戳,我們可以這樣:

var oldLog = console.logconsole.log = function() { oldLog.call(this, new Date().getTime()) oldLog.apply(this, arguments)}

同理,我們針對(duì)onLaunch 進(jìn)行猴子補(bǔ)丁

var oldAp = AppApp = function(options) { var oldOnLaunch = options.onLaunch options['onLaunch'] = function(t) {  // 做一些我們自己想做的事情  console.log('hello word....')  // 調(diào)用原來(lái)的onLaunch 方法  oldOnLaunch.call(this, t) }  // 調(diào)用原來(lái)的App 方法 oldApp(options)  // 想像一下,小程序內(nèi)部調(diào)用onLaunch 方法應(yīng)該是這樣子的: options.onLaunch(params)}// 問(wèn)題,有的時(shí)候,我們可能沒(méi)有注冊(cè)某一個(gè)事件,比如頁(yè)面的onShow, 所有,我們?cè)谔鎿Q的時(shí)候還需要判斷一下參數(shù)是否傳了對(duì)應(yīng)的方法Page({ onLoad (options) {}, onHide (options) {}})// 針對(duì)這種情況,我們需要這樣寫var oldPage = PagePage = function(options) { if (options['onShow']) {  // 如過(guò)有注冊(cè)onShow 這個(gè)回調(diào)  var oldOnShow = options.onShow  // onShow 方法調(diào)用時(shí)都是 傳了一個(gè)對(duì)象  options['onShow'] = function(t) {   // doSomething()   oldOnShow.call(this, t)  } } // 調(diào)用原來(lái)的Page 方法。 oldPage.apply(null, [].slice.call(arguments)) // 注意: 下面這兩種寫都會(huì)報(bào)錯(cuò): VM23356:1 Options is not object: {"0":{}} in pages/Badge.js 問(wèn)題具體原因暫時(shí)未找到。 // oldPage.call(null, arguments) // oldPage(arguments)}

通過(guò)上面的方法,我們可以攔截了 App 方法注冊(cè)的一些全局方法,比如 onLaunch , onShow, onHide, 和Page 注冊(cè)的事件如 onShow, onHide, onLoad, onPullDownRefresh, 等頁(yè)面注冊(cè)事件。

2.網(wǎng)絡(luò)請(qǐng)求的監(jiān)聽(tīng)

思路: 攔截微信的請(qǐng)求事件。

let Request = {   request: function (e) {    let success = e[0].success,     fail = e[0].fail,     beginTime = smaUtils.getTime(),     endTime = 0    // 攔截請(qǐng)求成功方法    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)     // 這里做上報(bào)的事情     // SMA.performanceReport(performance)     success && success.apply(this, [].slice.call(arguments))    }    // 攔截請(qǐng)求失敗方法    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)     // 這里做上報(bào)的事情     // SMA.performanceReport(performance)     fail && fail.apply(this, [].slice.call(arguments))    }   },  }    // 替換微信相關(guān)屬性  let oldWx = wx,   newWx = {}  for (var p in wx) {   if (Request[p]) {    let p2 = p.toString()    newWx[p2] = function () {     Request[p2](arguments)     // 調(diào)用原來(lái)的wx.request 方法     oldWx[p2].apply(oldWx, [].slice.call(arguments))    }   } else {    newWx[p] = oldWx[p]   }  }  // eslint-disable-next-line  wx = newWx

疑惑:為什么要使用替換整個(gè)wx對(duì)象的方法呢? 不直接用我們的request 方法 替換 wx.request 方法

var oldRequest = wx.requestwx.request = function(e) { // doSomething(); console.log('請(qǐng)求攔截操作...') oldRequest.call(this, e); // 調(diào)用老的request方法}// 結(jié)果報(bào)錯(cuò)了:// TypeError: Cannot set property request of [object Object] which has only a getter

3.錯(cuò)誤的監(jiān)聽(tīng)

3.1 攔截App里注冊(cè)的 onError事件

var oldAp = AppApp = function(options) { var oldOnError = options.onErrr options['onErrr'] = function(t) {  // 做一些我們自己想做的事情  console.log('統(tǒng)計(jì)錯(cuò)誤....', t)  // 調(diào)用原來(lái)的onLaunch 方法  oldOnError.call(this, t) }  // 調(diào)用原來(lái)的App 方法 oldApp(options)}

3.2 攔截 conole.error

console.error = function() {   var e = [].slice.call(arguments)   if (!e.length) { return true }   const currRoute = smaUtils.getPagePath()   // 統(tǒng)計(jì)錯(cuò)誤事件   // SMA.errorReport({event: eventMap.onError, route: currRoute, errrMsg: arguments[0]})   smaUtils.logInfo('捕捉到error 事件,', e)   oldError.apply(console, e) }

至此,我們已經(jīng)有能力在小程序發(fā)起請(qǐng)求時(shí),發(fā)生錯(cuò)誤時(shí),生命周期或者特殊函數(shù)回調(diào)時(shí),我們都能在里面做一些我們想要的數(shù)據(jù)統(tǒng)計(jì)功能了。

說(shuō)了這么多大家估計(jì)也看累了。鑒于篇幅,具體的代碼就不在這里貼了。

最終實(shí)現(xiàn)的數(shù)據(jù)統(tǒng)計(jì)模塊大致實(shí)現(xiàn)了以下功能:

  • 普通埋點(diǎn)信息上報(bào)功能
  • 錯(cuò)誤信息上報(bào)功能
  • 性能數(shù)據(jù)上報(bào)功能
  • 具體的上報(bào)時(shí)機(jī)支持配置
  • 支持指定網(wǎng)絡(luò)環(huán)境上報(bào)
  • 支持統(tǒng)計(jì)數(shù)據(jù)緩存到微信本地功能

整個(gè)統(tǒng)計(jì)代碼的配置文件如下:

const wxaConfig = { project: 'myMiniProgram', // 項(xiàng)目名稱 trackUrl: 'https://youhost.com/batch', // 后臺(tái)數(shù)據(jù)統(tǒng)計(jì)接口 errorUrl: 'https://youhost.com/batch', // 后臺(tái)錯(cuò)誤上報(bào)接口 performanceUrl: 'https://youhost.com/batch', // 后臺(tái)性能上報(bào)接口 version: '0.1', prefix: '_wxa_', priority: ['track', 'performance', 'error'], // 發(fā)送請(qǐng)求的優(yōu)先級(jí),發(fā)送時(shí),會(huì)依次發(fā)送 useStorage: true, // 是否開(kāi)啟storage緩存 debug: false, // 是否開(kāi)啟調(diào)試(顯示log) autoTrack: true, // 自動(dòng)上報(bào) onShow, onHide, 分享等 內(nèi)置事件 errorReport: false, // 是否開(kāi)啟錯(cuò)誤上報(bào) performanceReport: false, // 接口性能上報(bào) maxReportNum: 20, // 當(dāng)次上報(bào)最大條數(shù) intervalTime: 15, // 定時(shí)上報(bào)的時(shí)間間隔,單位 s, 僅當(dāng)開(kāi)啟了定時(shí)上報(bào)有效。 networkList: ['wifi', '4g', '3g'], // 允許上報(bào)的網(wǎng)絡(luò)環(huán)境 opportunity: 'pageHide' // pageHide、appHide、realTime(實(shí)時(shí)上報(bào))、timing(定時(shí)上報(bào)) 上報(bào)的時(shí)機(jī),四選一}export default wxaConfig

具體上報(bào)時(shí),上報(bào)的數(shù)據(jù)結(jié)構(gòu)大致長(zhǎng)這樣:

微信小程序,數(shù)據(jù)統(tǒng)計(jì),錯(cuò)誤統(tǒng)計(jì)

項(xiàng)目已傳到GitHub -> GitHub傳送門-wxa

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持VEVB武林網(wǎng)。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 福鼎市| 英超| 舟山市| 健康| 尼木县| 沭阳县| 涿鹿县| 永州市| 安国市| 酉阳| 视频| 阳新县| 禹城市| 康平县| 温宿县| 玛曲县| 卢龙县| 县级市| 资中县| 龙门县| 克山县| 长武县| 许昌县| 福海县| 霍山县| 连州市| 广东省| 施甸县| 东乡| 鸡泽县| 会宁县| 竹北市| 桦川县| 普陀区| 城固县| 浠水县| 巴里| 墨脱县| 桃源县| 休宁县| 澄城县|