环境
iphone: 7
ios: 15.3
微信:8.0.42
Vue: 2.6.14
Vant: 2.12.25
Axios: 0.19.2
问题描述
在微信IOS内置浏览器或者Safari中访问MPS(多页面)项目时,在离开页面之前(visibilitychange
事件中)会请求一个数据埋点的接口,跳转页面后再点击返回上一个页面,会显示“Network Error”。
相关代码:
1.页面vue代码:
export default {
methods: {
handleVisiable (e) {
switch (e.target.visibilityState) {
case 'hidden':
{
const timeStart = sessionStorage.getItem('timeStart') / 1000
const _duration = (Date.now() - timeStart) / 1000
// 埋点ajax请求
this.buryingPointFn({
event_name: 'certification_pageview',
event_type: 'PageView',
content: {
enter_time: Math.ceil(timeStart),
duration: Math.ceil(_duration)
}
})
}
break
case 'visible':
sessionStorage.setItem('timeStart', Date.now())
break
}
}
},
destroyed () {
document.removeEventListener('visibilitychange', this.handleVisiable)
}
}
2.axios请求响应拦截:
service.interceptors.response.use(
response => {
},
err => {
// 网络连接正常
if (err.response) {
err.message = codeMessage[err.response.status]
}
// 页面返回时显示Network Error消息就是从这里显示出来的
err.message && Toast.fail(err.message)
return Promise.reject(err)
}
)
调查结果
通过真机联调测试,发现返回页面时并没有进行任何ajax请求。那么这个Network Error的消息就不可能是返回页面后从页面发出的请求,所以该请求应该是跳转离开前一个页面前的数据埋点接口失败时抛出的消息。在使用 visibilitychange
事件处理 Ajax 请求时,因为当页面变为不可见状态时,浏览器会降低对该页面的资源分配,以节省电池寿命和网络带宽,因而可能会导致 Ajax 请求失败或被中断,使得axios抛出Network Error。IOS上浏览器为了提高加载速度,会对页面进行缓存(包括离开时的显示状态),所以当页面即使等待几分钟再返回时依然能在前一个页面显示出之前的Network Error的Toast消息。
为了验证IOS上浏览器会缓存完整页面,我们对页面URL链接进行修改,增加或减少链接上的参数,同时对应改变页面的一些内容,以便于区分不同链接参数对应不一样的页面展示。实验发现,同一个页面(之后链接参数不一样),即使页面内容更新到最新并重启服务器时,仍然可以通过不同的链接参数访问到对应设置不同的展示内容,说明浏览器根据访问的地址(包括链接参数),缓存了对应的完整页面,即使页面内容已经被更新。
解决方案
针对 visibilitychange
事件中的埋点接口对Network Error消息进行屏蔽处理:
// fix: 修复ios中页面返回时显示Network Error错误
if (!(err.message === 'Network Error' && err?.config?.url === '/**/**/track_up')) {
err.message && Toast.fail(err.message)
}