背景:
隨著業(yè)務(wù)的增加,我們服務(wù)器需要計(jì)算大量的用戶數(shù)據(jù)孝宗,導(dǎo)致用戶跟客服反應(yīng)頁(yè)面不能正常展示穷躁。反饋給開(kāi)發(fā)后,我們一看因妇,是服務(wù)器異常的錯(cuò)誤问潭。So,產(chǎn)品想看下我們到底有多少用戶頁(yè)面不能正常展示婚被?
方案:
- 后端人員直接在阿里云后臺(tái)去查哪些接口異常
- 前端做一個(gè)服務(wù)器報(bào)錯(cuò)頁(yè)睦授,這樣產(chǎn)品在小程序后臺(tái)能看到這個(gè)頁(yè)面的PV,UV
技術(shù)方案
因?yàn)闃I(yè)務(wù)龐大,所以我們不可能區(qū)在每個(gè)頁(yè)面加上重新加載的邏輯摔寨。所以初步考慮使用全局重新加載去枷。
需要解決的問(wèn)題都有哪些?
- 首先我們要有網(wǎng)絡(luò)請(qǐng)求失敗的全局控制權(quán)(要不然就需要在每個(gè)頁(yè)面處理失敗的情況)
- 需要定義好網(wǎng)絡(luò)失敗后是如何跳轉(zhuǎn)到重載頁(yè)(R)的(用wx.redirectTo是复,wx.reLaunch還是其他)
- 點(diǎn)擊錯(cuò)誤頁(yè)的“重新加載”删顶,如何返回或跳轉(zhuǎn)到出錯(cuò)頁(yè)(E)(用wx.redirectTo,wx.reLaunch還是其他)
- 跳轉(zhuǎn)到出錯(cuò)頁(yè)后淑廊,如何重新加載數(shù)據(jù)(把所有請(qǐng)求都放在Page.onShow()里面?)
- 那如果從出錯(cuò)頁(yè)的上個(gè)界面(P)傳到出錯(cuò)頁(yè)(E)options逗余,那重載頁(yè)(R)又將如何處理?
- 點(diǎn)擊重新加載跟返回季惩,我們希望效果效果一樣录粱,又該如何操作?
實(shí)踐的方式如下
第一個(gè)問(wèn)題: 比較好解決画拾,我們基于wx.request已經(jīng)封裝了為fetch(如果還在用wx.request的項(xiàng)目可以考慮封裝下啥繁,好處多多)∏嗯祝基于fetch我們可以用res.statusCode來(lái)判斷服務(wù)器是否出錯(cuò)旗闽。
第二個(gè)問(wèn)題: 暫且先不說(shuō)具體的跳轉(zhuǎn)方式是怎樣的,就跳轉(zhuǎn)的url這個(gè)怎么定義也需要我們來(lái)討論下蜜另。為什么這么說(shuō)适室,因?yàn)槲覀兊募軜?gòu)涉及到了分包。分包加載意味著我們的代碼不僅僅是在pages下面举瑰,還放在了package下捣辆。
基于此,我們?cè)谔D(zhuǎn)的時(shí)候此迅,url能直接寫(xiě)成'../serverError/serverError'嗎汽畴?在主包下面可以正常跳轉(zhuǎn)促煮,但是在分包下,路徑是'package/serverError/serverError'整袁,這樣跳肯定不行菠齿。url應(yīng)該是根目錄下的路徑,所以'/pages/serverError/serverError'坐昙。
路徑確認(rèn)后绳匀,我們可以跳轉(zhuǎn)了。如果是wx.redirectTo(關(guān)閉當(dāng)前頁(yè)面炸客,跳轉(zhuǎn)到應(yīng)用內(nèi)的某個(gè)頁(yè)面)疾棵,想象下關(guān)閉E跳轉(zhuǎn)到R,點(diǎn)擊重新加載痹仙,再關(guān)閉R跳轉(zhuǎn)到E是尔,這么跳轉(zhuǎn)路徑復(fù)雜,用戶體驗(yàn)不好开仰,并且options的參數(shù)需要逐級(jí)傳遞拟枚。wx.reLaunch類(lèi)似。我們用所以我們選擇wx.navigateTo众弓。
第三個(gè)問(wèn)題: 綜合問(wèn)題二的解釋?zhuān)氐紼恩溅,我們用wx.navigateBack。
第四個(gè)問(wèn)題: 如果從R用wx.navigateBack回到E的話谓娃,肯定會(huì)觸發(fā)E.onShow()方法脚乡。但是有些請(qǐng)求我們除了寫(xiě)在Page.onShow()里,還有些是寫(xiě)在Page.onLoad()里的滨达,所以我們必須想辦法調(diào)起E.onLoad()奶稠。
大家對(duì)于getCurrentPages()這個(gè)方法肯定不陌生,官方定義是來(lái)獲取當(dāng)前頁(yè)面棧捡遍,我們一般用它來(lái)獲取當(dāng)前頁(yè)面路徑锌订。其實(shí)在這個(gè)過(guò)程中,我們是能拿到當(dāng)前頁(yè)面的實(shí)例的稽莉,并且實(shí)例里面有route(頁(yè)面路徑)options(頁(yè)面?zhèn)鬟f參數(shù))data(頁(yè)面初始參數(shù))以及各種function()等等瀑志。
利用previousPageClass()我們可以拿到E的實(shí)例,也就可以拿到E.options污秆,當(dāng)然我們也可以調(diào)E.onLoad()。
util.js
// 獲取當(dāng)前路徑
function currentPagePath() {
let pageData = getCurrentPages()
if (pageData.length >= 1) {
let len = pageData.length - 1
let data = pageData[len]
return data.route
} else {
return ''
}
}
// 獲取上個(gè)界面的實(shí)例
function previousPageClass() {
let pageData = getCurrentPages()
if (pageData.length >= 2) {
let len = pageData.length - 2
let preClass = pageData[len]
return preClass
} else {
return ''
}
}
module.exports = {
currentPagePath,
previousPageClass
}
第五個(gè)問(wèn)題: 基于問(wèn)題的四的方案昧甘,我們可以調(diào)E.onLoad(E.options)來(lái)將我們的參數(shù)回傳回去良拼。
第六個(gè)問(wèn)題: 點(diǎn)擊返回,相當(dāng)于頁(yè)面卸載充边,也就是執(zhí)行了R.onUnload(),這個(gè)時(shí)候我們只需要執(zhí)行E.onLoad(E.options)這個(gè)方法庸推,把options傳過(guò)去常侦,以及調(diào)用起E.onLoad()就OK了。
但是點(diǎn)擊重新加載贬媒,我們是調(diào)的wx.navigateBack()聋亡,這個(gè)方法也會(huì)走R.onUnload()。這是時(shí)候可能有些苦惱了际乘,我們隱藏掉返回按鈕坡倔?發(fā)現(xiàn)官方并沒(méi)有提供此方法。禁用R.onUnload()脖含,好像也不行罪塔。因?yàn)镽.onUnload()是在點(diǎn)擊重新加載后才執(zhí)行的,所以我們可以記錄下用戶是否點(diǎn)擊了重新加載的行為养葵。然后我們通過(guò)記錄的行為征堪,即便用戶點(diǎn)擊了重新加載,然后觸發(fā)了R.onUnload()关拒,我們不去執(zhí)行E.onLoad(E.options)就OK了佃蚜。
// pages/serverError/serverError.js
import { previousPageClass } from '../../utils/util.js'
let isClickReload = false
Page({
onLoad: function (options) {
isClickReload = false
},
onUnload: function () {
if(!isClickReload) {
this.callbackParams()
}
},
/**
* 點(diǎn)擊事件
*/
clickReload: function (e) {
isClickReload = true
wx.navigateBack()
this.callbackParams()
},
// 點(diǎn)擊返回,參數(shù)回傳
callbackParams: function () {
let preOptions = previousPageClass().options
previousPageClass().onLoad(preOptions)
}
})
至此所有問(wèn)題着绊,基本都已解決爽锥。
Demo代碼附上,歡迎參考畔柔。