前言

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输

很多网站为了实现推送技术,所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。

而HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯

看过一个很有趣的形容:

  • 轮询就是:
 前台:后台你好了没有?(3秒后。。。)
 后台:没有。
 前台:后台你好了没有?(3秒后。。。)
 后台:没有。
 前台:后台你好了没有?(3秒后。。。)
 后台:好了。。
  • websocket就是:
前台:后台你好,我来拿水果了!
后台:给你苹果。(1秒后。。)
后台:给你梨子。(10秒后。。)
后台:给你香蕉,我没水果了。
前台:好了,我走了!

正文

1. 建立websocket

实现效果:点击按钮建立连接,页面关闭时关闭连接。

  • 代码如下:
<template>
    <div>
        <button @click="initSocket">建立websocket连接</button>
    </div>
</template>
<script>
    export default {
        data() {
            return {
                webSocket: null,
                url: '197.2.1.3:8088',
                types: '给后台参数'
            }
        },
        methods: {
            // 建立连接
            initSocket() {
                // 有参数的情况下:
                let url = `ws://${this.url}/${this.types}`
                // 没有参数的情况:接口
                // let url1 = 'ws://localhost:9998'
                this.webSocket = new WebSocket(url)
                this.webSocket.onopen = this.webSocketOnOpen
                this.webSocket.onclose = this.webSocketOnClose
                this.webSocket.onmessage = this.webSocketOnMessage
                this.webSocket.onerror = this.webSocketOnError

            },
            // 建立连接成功后的状态
            webSocketOnOpen() {
                console.log('websocket连接成功');
            },
            // 获取到后台消息的事件,操作数据的代码在onmessage中书写
            webSocketOnMessage(res) {
                // res就是后台实时传过来的数据
                console.log(res);
                 //给后台发送数据
                this.webSocket.send("发送数据");
            },
            // 关闭连接
            webSocketOnClose() {
                this.webSocket.close()
                console.log('websocket连接已关闭');
            },
            //连接失败的事件
            webSocketOnError(res) {
                console.log('websocket连接失败');
                // 打印失败的数据
                console.log(res);
            }
        },
        created() {
            // 页面打开就建立连接,根据业务需要
            this.initSocket()
        },
        destroyed() {
            // 页面销毁关闭连接
            this.webSocket.close()
        },
    }
</script>

谨记:在生命周期结束的时候关闭websocket连接,除非业务需要可以不关,不然很耗内存。

destroyed() {
            // 页面销毁关闭连接
         this.webSocket.close()
 },

2. axios 轮询

实现效果:点击按钮,建立轮询,3秒之后判断状态,成功就关闭,失败就继续发送请求。

ps:本身没有想写轮询的,但还是附上~~毕竟现在大部分的方式还是轮询,因为我目前的项目是vue框架下,所以代码也基本是vue,原生或其他框架类似。

  • 代码:
<template>
    <div>
        <button @click="getStatus">发请求拿数据</button>
        <span>状态:{{status}}</span>
    </div>
</template>
<script>
    export default {
        data() {
            return {
                status: ''
            }
        },
        computed: {
            // 计算属性
            statusData() { return this.status }
        },
        watch: {
            statusData: function (newval) {
                // 当返回的新值为创建中的时候,保持3秒轮询
                if (newval == 'creating') {
                    var timer = setInterval(() => {
                        setTimeout(this.getStatus, 0)
                    }, 3000)
                }
                // 当返回的新值为成功的时候,关闭定时器,结束轮询
                if (newval == 'success') {
                    clearInterval(timer)
                }
                // 当页面关闭的时候,结束轮询,否则就会一直发请求,
                //使用$once(eventName, eventHandler)一次性监听事件
                this.$once('hook:boforeDestory', () => {
                    clearInterval(timer)
                })
            }
        },
        methods: {
            getStatus() {
                getStatusApi().then(res => {
                    if (res.status == 200) this.$message.error('请求失败')
                    this.status = res.data.status
                })
            }
        },
    }
</script>

提示:

  • 有童鞋提问:watch是否可以直接监听status,不使用computed?

    其实这样都可以,只是我自己的书写习惯,我习惯的这种写法的使用情况是:watch如果想要监听对象的单个属性的变化,,不用深度监听全部,用computed作为中间件转化,就可以取到对应的属性值。

  • 还有了解vue的童鞋肯定有人好奇,为什么不在beforeDestory,关闭而在,this.$once()中关闭定时器,因为由于路由跳转,并不会触发beforeDestory,所以定时器清不掉!

结语

今天木有结语!

如果本文对你有帮助的话,请给我点赞打call哦~o( ̄▽ ̄)do
有其他问题留言 over~

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐