在vuex的异步函数actions调用了初始化的方法,然后把触发contentSocket 发法来创建实例,并绑定在state上的ws上,这里一定要把commit 来作为参数,一边socket实例能触发方法改变state,我们知道了socket实例如何绑定和commit传递的了 ,下面我们看看websocket.js 整个核心调度是怎么运作的。
socket.prototype.$socket_init = function (callback) {
const _this = this
if (_this.closeWs) {
throw new Error('socket is closed ,$socker_init is fail , all methods is invalid')
const token = window.localStorage.getItem('token') || window.sessionStorage.getItem('token') || null
if (!token) {
throw new Error('token is underfined')
const handerErrorMachine = () => {
if (_this.errorResetNumber === 4) {
_this.errorResetNumber = 0
_this.errorResetTimer = null
_this.errorFrom = 0
_this.errorDispatchOpen = false
_this.ws = null
console.log('socket连接失败')
return
_this.errorResetTimer = setTimeout(() => {
/* 失败重新连接 */
_this.$soctket_init()
_this.errorResetNumber++
}, _this.errorResetNumber * 2000)
const errorDispatch = (eventment) => { //错误调度
let event = eventment
return function () {
if (_this.errorFrom === 0 && _this.errorDispatchOpen) {
_this.errorFrom = event
event === 1 ? console.log('web socket has failed from closeState ') : console.log('web socket has failed from errorState ')
if (_this.errorFrom === event && !_this.closeWs) {
_this.errorResetTimer && clearTimeout(_this.errorResetTimer)
handerErrorMachine()
if (this.timer) clearTimeout(this.timer)
_this.ws = new WebSocket(socketUrl + '?token=' + token) //这里才进行了真正的socket连接
_this.ws.onopen = function () {
callback && callback()
_this.errorResetNumber = 0
_this.errorResetTimer = null
_this.errorFrom = 0
_this.errorDispatchOpen = true
/* 接受消息,改变状态 */
_this.$soctket_subscribe()
_this.$soctket_heartSoctket()
console.log('web socket has connected ')
_this.ws.onclose = errorDispatch(1)
_this.ws.onerror = errorDispatch(2)
这里才是真正的socket连接 和一些错误处理方式 , 这里把socket连接和构造函数中的ws绑定在一起,以及一个连接失败的调度机制 , 里边有一个之前一直提到的方法,socketsubscribe()没错就是它,监听后端传来信息的方法,并且触发vuex,commit方法,改变state,通知view视图更新,值得提出的一点是.socket_subscribe() 没错就是它,监听后端传来信息的方法,并且触发vuex ,commit方法,改变state,通知view视图更新,值得提出的一点是.socketsubscribe()没错就是它,监听后端传来信息的方法,并且触发vuex,commit方法,改变state,通知view视图更新,值得提出的一点是.socket_heartSoctket() 是一个心脏搏动机制,我们知道如果socket连接长时间没有通话会自动断开连接,所以这里有一个心脏搏动机制。接下来我们看一下,socket_subscribe 方法。
subscribe订阅接受信息,改变状态
* 接受广播 -> 督促view更新
socket.prototype.$socket_subscribe = function () {
const _this = this
_this.ws.onmessage = function (res) {
if (_this.actions) {
if (isType(_this.actions) !== 'Function') {
throw new Error('actions')
} else {
_this.commit(..._this.actions(res.data))
} else {
_this.commit(res.data)
_this.$soctket_heartSoctket()
我们才看到原来之前vuex传进来的 commit 在这里发挥了作用,也就是触发mutations 来改变state里边 的数据 ,来重新渲染试图 ,接下来我们看一下emit触发器。
emit 任意组件传递信息
* 触发器->发布信息
* @param callback 状态处理
* @param value 数据处理
socket.prototype.$socket_emit = function (value, callback) {
const _this = this
const poll = function () {
return _this.ws.readyState
if (callback && isType(callback) !== 'Function') {
throw new Error('$socket_emit arugment[1] must be a function')
if (!_this.ws) {
throw new Error('$socket dispatch is fail please use $socket_open method')
if (_this.ws.readyState === 1) { // 连接成功状态
_this.ws.send(value)
_this.$soctket_heartSoctket()
callback && callback()
else if (_this.ws.readyState === 0) { // 连接中状态 ,轮询查询连接
eventPoll(poll, 1, 500, () => {
_this.ws.send(value)
_this.$soctket_heartSoctket()
callback && callback()
else { // 失败重新连接
_this.$soctket_init(() => {
_this.$soctket_emit(value, callback)
这个就是之前提到的emit 触发器 用来在vue中调用, 来向服务端发起数据通信,就实现了双向的数据通信, 里边有一个轮询器 来轮询eventPoll ,websocket 的状态是否是已经连通的状态 ,那么在Vue文件中是怎么调用emit的呢 ,很简单就是调用vuex中之前绑定的state里边的wx。
任意组件中
const { ws } = this.$store.state.socket
ws.$soctket_emit(JSON.stringify({
data: 'hello , world'
}), () => {
console.log('发送成功')
就是这么简单触发的。以上整个机制都已经讲解了一边,那么还有心跳机制,给大家介绍一下。
heart心跳机制
* 心脏搏动机制->防止断开连接
socket.prototype.$soctket_heartSoctket = function () {
if (this.timer) clearTimeout(this.timer)
console.log(this.timer)
this.timer = setTimeout(() => {
if (this.ws.readyState === 1 || this.ws.readyState === 0) {
this.ws.send('heart , socket')
this.$soctket_heartSoctket()
} else {
this.$soctket_init()
}, 59000)
就是不断向服务端发起消息,来防止断开连接。 还有两个方法来控制ws的连接和关闭。
* 开启,关闭 socket
* 关闭socket连接
socket.prototype.$soctket_close = function () {
if (this.timer) clearTimeout(this.timer)
if (this.errorResetTimer)clearTimeout(this.errorResetTimer)
this.closeWs = true
this.ws.close()
* 重启socket连接
socket.prototype.$soctket_open = function () {
if (!this.closeWs) {
throw new Error('socket is connected')
this.timer = null
this.errorResetNumber = 0
this.closeWs = false
this.errorFrom = 0
this.errorResetTimer = null
this.errorDispatchOpen = true
this.heartSocketOpen = false
this.closeWs = false
this.$soctket_init()
vue-socket.io接收不到数据问题的解决方法
最近公司的一个vue项目用到了vue-socket.io来处理socket数据传输,之前用过socket.io-client,现在知道vue-socket.io是基于socket.io-client的一层封装,将socket挂于全局从而更方便的书写。
于是把代码拉取下来运行:
什么鬼,同样的代码为什么我的就接收不到数据,自己新建一个测试一下吧!
先用express和socket.io搭个小socket服务器:
let express = require(\'express\');
let app = express();
let server= require(\'http\').Server(app);
let io = require(\'socket.io\')(server);
io.on(\'connect\', (socket) => {
setInterval(() => {
socket.emit(\'hi\',\'hello\')
},2000)
socket.on(\'hello\', (data) => {
console.log(\'hello\',data)
socket.emit(\'hi\',\'get it\')
socket.on(\'disconnect\', (data) => {
console.log(\'断开\', data)
server.listen(8080);
再搭个vue-cli3环境,main.js里use一下socket:
import Vue from \'vue\'
import App from \'./App.vue\'
import VueSocketIO from \'vue-socket.io\'
Vue.config.productionTip = false
Vue.use(new VueSocketIO({
debug: true,
connection: \'http://127.0.0.1:8080\',
new Vue({
render: h => h(App),
}).$mount(\'#app\')
再去组件里监听一下:
<script>
export default {
sockets: {
connect() {
console.log(\'链接成功\');
disconnect() {
console.log(\'断开链接\')
reconnect() {
console.log(\'重新链接\')
hi(res) {
console.log(\'VueSocketIO\', res)
</script>
为什么,是socket数据没发送过来吗?我装个socket.io-client试试:
import io from \'socket.io-client\'
export default {
mounted() {
io(\'http://127.0.0.1:8080\').on(\'hi\', (res) => {
console.log(\'socket.io-client\', res)
没问题,收到了,所以现在是socket已经连接上了,客户端可以向服务端正常发送数据,但服务端也向客户端发送数据了,上面用socket.io-client可以正常接收已经证明这一点了,问题是vue-socket.io没有正确写法去接收数据,似乎api上的写法出bug了。
打印一下this发现因为引入vue-socket.io的原因,this上面挂了一个sockets属性:
this.sockets下有一个listener属性,看这个名字就感觉有戏,试一下:
this.sockets.listener.subscribe(\'hi\', (data) => {
console.log(\'++++++++++\',data)
3. 分享目的仅供大家学习和交流,请不要用于商业用途!
4. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
5. 本站所有资源来源于站长上传和网络,如有侵权请邮件联系站长!
6. 没带 [亲测] 代表站长时间紧促,站长会保持每天更新 [亲测] 源码 !
7. 盗版ripro用户购买ripro美化无担保,若设置不成功/不生效我们不支持退款!
8. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
9. 如果你也有好源码或者教程,可以到审核区发布,分享有金币奖励和额外收入!
10.如果您购买了某个产品,而我们还没来得及更新,请联系站长或留言催更,谢谢理解 !
GG资源网
»
websocket长连接和公共状态管理方案(vue-socket.io接收不到数据问题的解决方法)