前言
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~