如何处理浏览器的断网状况?

offline.jpg

好的断网处理会让人很温馨:lol的断线重连,王者荣耀的断线重连 能够确保游戏的继续进行css

坏的断网处理甚至不处理会出bug:好比我手上的项目就出了个bug 业务人员表示很是苦恼html

网络问题一直是一个很值得关注的问题。前端

好比在慢网状况下,增长loading避免重复发请求,使用promise顺序处理请求的返回结果,或者是增长一些友好的上传进度提示等等。vue

那么你们有没有想过断网状况下该怎么作呢?好比说网络正常->断网->网络正常。git

其实我一直也没想过,直到组里的测试测出一个断网致使的bug,让我意识到重度依赖网络请求的前端,在断网状况下可能会出现严重的bug。github

所以我将在这里记录一下本身对系统断网状况下的处理,一方面避免bug产生,一方面保证用户及时在应用内知道网络已经断开链接web

  • 概览
  • 用于检测浏览器是否连网的navigator.onLine
  • 断网事件"offline"和连网事件"online"
  • 断网处理项目实战segmentfault

    • 思路和效果
    • 断网处理组件使用
    • 断网处理组件详情
    • 发现
  • 参考资料

概览

为了构建一个 “断网(offline)可用”的web应用,你须要知道应用在何时是断网(offline)的。
不单单要知道何时断网,更要知道何时网络恢复正常(online)。
能够分解陈本下面两种常见状况:promise

  1. 你须要知道用户什么时候online,这样你能够与服务器之间re-sync(从新同步)。
  2. 你须要知道用户什么时候offline,这样你能够将你未发出的请求过一段时间再向服务器发出。

一般能够经过online/offline事件去作这个事情。浏览器

用于检测浏览器是否连网的navigator.onLine

navigator.onLine

  • true online
  • false offline

能够经过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)...

断网事件"offline"和连网事件"online"

浏览器有两个事件:"online" 和 "offline".
这两个事件会在浏览器在online mode和offline mode之间切换时,由页面的<body>发射出去。

事件会按照如下顺序冒泡:document.body -> document -> window。

事件是不能去取消的(开发者在代码上不能手动变为online或者offline,开发时使用开发者工具能够)。

注册上下线事件的几种方式

最最建议window+addEventListener的组合。

  • 经过window或document或document.body和addEventListener(Chrome80仅window有效)
  • 为document或document.body的.ononline或.onoffline属性设置一个js函数。(注意,使用window.ononline和window.onoffline会有兼容性的问题)
  • 也能够经过标签注册事件<body ononline="onlineCb" onoffline="offlineCb"></body>

例子

image

image

<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组件封装出离线处理组件,在须要到的页面引入便可。

思路和效果

只要作到断网提醒+遮罩,上线提醒-遮罩便可。

  • 监听offline,断网给出提醒和遮罩:网络已断开,请检查网络链接。
  • 监听online,连网给出提醒和遮罩:网络已链接。

断网处理组件使用

<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>

发现

  • offline和online事件:window有效,document和document.body设置无效

手上的项目只运行在Chrome浏览器,只有为window设置offline和online才生效。
运行环境:"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36

  • 为position增长2s的transition的避免屏闪

参考资料:

期待和你们交流,共同进步,欢迎你们加入我建立的与前端开发密切相关的技术讨论小组:

努力成为优秀前端工程师!
相关文章
相关标签/搜索