Open
Description
背景
页面有个倒计时组件,倒计时结束时会调用接口获取最新的数据。但是有个用户反馈倒计时结束时接口报错了,刷新页面就正常了。看了下日志接口请求报了Timeout错误,难道用户的网络不稳定?但是为啥刷新页面又正常了?
定位原因
尝试复现用户的问题却没有重现问题。参照页面切到后台后浏览器会优化定时器的思路,难道网络请求也被优化了?按照这个思路利用Safari查看移动端请求情况,在一顿操作(来回把浏览器切换到后台)后终于复习了用户的问题。可以看到这次请求时间大约9s:
对比浏览器在前台和后台时接口请求响应时间差距很大(如下图):
有时会出现大于30s的情况,加上接口的超时时间是30s所以就出现Timeout错误了。
解决方案
临时方案
页面不可见时暂停定时器,等用户再次进来页面时再重新启动定时器:
useDocumentVisibilityChange((visible) => {
if (visible) {
// 启动定时器
} else {
// 暂停定时器
}
});
测试一下居然不行!!!!理论上方案可行,但实际为啥不行呢?浏览器从后台切回前台时也触发了DocumentVisibilityChange
事件。
从视觉上看浏览器从后台切回前台时会有个过渡动画,DocumentVisibilityChange
事件在动画前触发的。等动画执行完后再启动定时呢?稍微调整了下代码(如下)解决了这个问题。
useDocumentVisibilityChange((visible) => {
if (visible) {
setTimeout(() => {
// 启动定时器
}, 240)
} else {
// 暂停定时器
}
});
长久方案 ???
目前还没弄清楚为什么浏览器切到后台后接口请求被挂起了。