好的断网处理会让人很舒适:lol的断线重连,王者荣耀的断线重连 可以确保游戏的继续进行
坏的断网处理甚至不处理会出bug:比如我手上的项目就出了个bug 业务人员表示非常苦恼
网络问题一直是一个很值得关注的问题。
比如在慢网情况下,增加loading避免重复发请求,使用promise顺序处理请求的返回结果,或者是增加一些友好的上传进度提示等等。
那么大家有没有想过断网情况下该怎么做呢?比如说网络正常->断网->网络正常。
其实我一直也没想过,直到组里的测试测出一个断网导致的bug,让我意识到重度依赖网络请求的前端,在断网情况下可能会出现严重的bug。
因此我将在这里记录一下自己对系统断网情况下的处理,一方面避免bug产生,一方面保证用户及时在应用内知道网络已经断开连接
为了构建一个 “断网(offline)可用”的web应用,你需要知道应用在什么时候是断网(offline)的。 不仅仅要知道什么时候断网,更要知道什么时候网络恢复正常(online)。 可以分解陈本下面两种常见情况:
通常可以通过online/offline事件去做这个事情。
navigator.onLine
可以通过network的online选项切换为offline,打印navigator.onLine验证。
当浏览器不能连接到网络时,这个属性会更新。规范中是这样定义的:
The navigator.onLine attribute must return false if the user agent will not contact the network when the user follows links or when a script requests a remote page (or knows that such an attempt would fail)...
浏览器有两个事件:"online" 和 "offline".
这两个事件会在浏览器在online mode和offline mode之间切换时,由页面的<body>
发射出去。
事件会按照以下顺序冒泡:document.body -> document -> window。
事件是不能去取消的(开发者在代码上不能手动变为online或者offline,开发时使用开发者工具可以)。
最最建议window+addEventListener的组合。
<body ononline="onlineCb" onoffline="offlineCb"></body>
<div id="status"></div> <div id="log"></div> 复制代码
window.addEventListener('load', function() { var status = document.getElementById("status"); var log = document.getElementById("log"); function updateOnlineStatus(event) { var condition = navigator.onLine ? "online" : "offline"; status.innerHTML = condition.toUpperCase(); log.insertAdjacentHTML("beforeend", "Event: " + event.type + "; Status: " + condition); } window.addEventListener('online', updateOnlineStatus); window.addEventListener('offline', updateOnlineStatus); }); 复制代码
其中insertAdjacentHTML是在标签节点的邻近位置插入,可以查阅:DOM进阶之insertAdjacentHTML
基于vue以及iView的Spin,Notice组件封装出离线处理组件,在需要到的页面引入即可。
只要做到断网提醒+遮罩,上线提醒-遮罩即可。
<OfflineHandle :offlineTitle = "断网处理标题" :desc="断网处理描述" :onlineTitle="连网提醒" > </OfflineHandle> 复制代码
<!--OfflineHandle.vue--> <template> <div v-if="spin" class="offline-mark"> <Spin size="large" fix> <h2>{{offlineTitle}}</h2> <p>{{desc}}</p> </Spin> </div> </template> <script> export default { name: 'offline-handle', props: { offlineTitle: { type: String, default: '网络已断开,请检查网络连接。', }, onlineTitle: { type: String, default: '网络已连接', }, desc: { type: String, default: '', }, duration: { type: Number, default: 4.5, }, }, data() { return { spin: false, }; }, mounted() { window.addEventListener('offline', this.eventHandle); window.addEventListener('online', this.eventHandle); }, beforeDestroy() { window.removeEventListener('offline', this.eventHandle); window.removeEventListener('online', this.eventHandle); }, methods: { eventHandle(event) { const type = event.type === 'offline' ? 'error' : 'success'; this.$Notice[type]({ title: type === 'error' ? this.offlineTitle : this.onlineTitle, desc: type === 'error' ? this.desc : '', duration: this.duration, }); setTimeout(() => { this.spin = event.type === 'offline'; }, 1500); }, }, }; </script> <style lang="scss" scoped> .offline-mark { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; z-index: 9999; transition: position 2s; } /deep/.ivu-spin-fix { text-align: left; font-size: 20px; h2 { color: rgba(0, 0, 0, 0.8); } p { margin-top: 20px; color: red; font-weight: bold; } } </style> 复制代码
参考资料:
期待和大家交流,共同进步,欢迎大家加入我创建的与前端开发密切相关的技术讨论小组:
- SegmentFault技术圈:ES新规范语法糖
- SegmentFault专栏:趁你还年轻,做个优秀的前端工程师
- 知乎专栏:趁你还年轻,做个优秀的前端工程师
- Github博客: 趁你还年轻233的个人博客
- 前端开发QQ群:660634678
- 微信公众号: 生活在浏览器里的我们 / excellent_developers
努力成为优秀前端工程师!