前言
vue項(xiàng)目中有使用到socket
長(zhǎng)連接,之前一直都是都是使用vue-socke.io
[github地址]抵蚊,但最近在使用時(shí)施绎,出了一些莫名奇妙的bug,也是為此掉了不少頭發(fā)贞绳,最后還是解決了谷醉。關(guān)于socket
相關(guān)內(nèi)容介紹以及使用場(chǎng)景,這里不會(huì)做太多介紹(主要是懶)冈闭,可以翻看其他文章俱尼。本文主要介紹如何使用,以及再使用時(shí)需要注意一些什么萎攒。關(guān)于文章中使用的代碼遇八,我放上github地址臭猜。前端小鳥(niǎo)一枚,立誓要成為前端菜鳥(niǎo)押蚤,不足地方留言指出蔑歌,小子謝過(guò)。
安裝
這里我們安裝vue.socket.io
模塊和socket.io-client
模塊揽碘,也可以不用socket.io-client
模塊次屠,請(qǐng)往下看。
cnpm i vue-socket.io -S
cnpm i socket.io-client -S
yarn vue-socket.io
yarn i socket.io-client
vue 客戶端使用
- 使用
socket.io-client
連接
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import VueSocketIO from 'vue-socket.io'
import SocketIO from "socket.io-client"
Vue.config.productionTip = false
// socket 連接參數(shù)
const socketOptions = {
autoConnect: false, // 自動(dòng)連接 這里為我項(xiàng)目需求 需要在指定情況下才連接socket
}
// 注冊(cè)
Vue.use(
new VueSocketIO({
debug: true , // debug調(diào)試雳刺,生產(chǎn)建議關(guān)閉
connection: SocketIO("127.0.0.1:1024", socketOptions),
store, // 如果沒(méi)有使用到store可以不用寫(xiě)
})
)
new Vue({
// 這里為全局監(jiān)聽(tīng)socket事件消息劫灶,監(jiān)聽(tīng)函數(shù)這里只寫(xiě)了一點(diǎn),其實(shí)很有很多事件掖桦。
sockets: {
connecting() {
console.log('正在連接')
},
disconnect() {
console.log("Socket 斷開(kāi)");
},
connect_failed() {
cosnole.log('連接失敗')
},
connect() {
console.log('socket connected')
}
},
router,
store,
render: h => h(App)
}).$mount('#app')
-
字符串連接
如果是正常使用本昏,項(xiàng)目啟動(dòng)就連接socket,可以不需要加載
socket.io-client
模塊枪汪,直接使用涌穆。
// 注冊(cè)
Vue.use(
new VueSocketIO({
debug: true , // debug調(diào)試,生產(chǎn)建議關(guān)閉
connection: 127.0.0.1:1024,
store, // 如果沒(méi)有使用到store可以不用寫(xiě)
})
)
- 組件中使用
<template>
<div id="app">
<div id="nav">
<button @click="connect">連接socket</button>
<button @click="sendMessage">發(fā)送數(shù)據(jù)</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
}
},
methods:{
// 連接socket
connect() {
this.$socket.open() // 開(kāi)始連接socket
// 訂閱事件
this.sockets.subscribe('welcome', data => {
console.log('welcome data ', data)
})
},
// 發(fā)送消息
sendMessage() {
this.$socket.emit('hello', '這里是客戶端')
}
},
sockets:{
//
welcome: data => {
console.log('welcome data ', data)
}
}
}
</script>
客戶端使用總結(jié)
客戶端自帶監(jiān)聽(tīng)事件
- connect:連接成功
- connecting:正在連接
- disconnect:斷開(kāi)連接
- connect_failed:連接失敗
- error:錯(cuò)誤發(fā)生雀久,并且無(wú)法被其他事件類(lèi)型所處理
- reconnect_failed:重連失敗
- reconnect:成功重連
- reconnecting:正在重連
監(jiān)聽(tīng)自定義事件
- 全局監(jiān)聽(tīng)
sockets:{
welcome: data => {
console.log('welcome data', data)
}
}
- 組件內(nèi)監(jiān)聽(tīng)
this.sockets.subscribe('welcome', data => {
console.log('welcome', data)
})
發(fā)送消息
注意:監(jiān)聽(tīng)用的是this.sockets
宿稀,發(fā)送消息是this.$socket
,不要弄混赖捌。
this.$socket.emit('hello', '這里是客戶端')
關(guān)于跨域問(wèn)題
socket會(huì)存在跨域問(wèn)題祝沸,之前看文章又說(shuō)到在vue.config.js
中配置代理,差不多和后臺(tái)接口代理配置一樣越庇,但我試過(guò)好像沒(méi)啥鳥(niǎo)用罩锐,如果有知道的同學(xué)麻煩留言告訴一聲,實(shí)際項(xiàng)目中的解決方式還是后端配置跨域問(wèn)題卤唉。
服務(wù)端使用
這里為啥要講服務(wù)端使用涩惑,主要是為了讓同學(xué)更好的體驗(yàn)socket,其次是為了引出后面的bug搬味,也是一個(gè)擴(kuò)展知識(shí)把境氢,是不是覺(jué)得自己賺了??。本地開(kāi)啟socket服務(wù)可以更好的進(jìn)行調(diào)試碰纬。服務(wù)端主要還是使用node
萍聊,畢竟咱也不會(huì)java、python....悦析,這里以及配置了socket跨域寿桨。
/*
* @Descripttion:
* @version:
* @Author: fanliu
* @Date: 2020-06-19 18:22
* @LastEditors: fanliu
* @LastEditTime: 2020-06-19 18:30
*/
var http = require('http');
var io = require('socket.io');
// 創(chuàng)建server服務(wù)
var server = http.createServer(function (req, res) {
var headers = {};
headers["Access-Control-Allow-Origin"] = "*";
headers["Access-Control-Allow-Methods"] = "POST, GET, PUT, DELETE, OPTIONS";
headers["Access-Control-Allow-Credentials"] = true;
headers["Access-Control-Max-Age"] = '86400'; // 24 hours
headers["Access-Control-Allow-Headers"] = "X-Requested-With, Access-Control-Allow-Origin, X-HTTP-Method-Override, Content-Type, Authorization, Accept";
res.writeHead(200, headers);
res.end();
});
// 啟動(dòng)服務(wù)器 監(jiān)聽(tīng) 1024 端口
server.listen(1024,function() {
console.log('server runing at 127.0.0.1:1024')
})
// 啟動(dòng)socket服務(wù)
var socket = io.listen(server, {origins: '*:*'});
// 監(jiān)聽(tīng)客戶端連接
socket.on('connection',function(socket) {
console.log('客戶端有連接')
// 監(jiān)聽(tīng)客戶端斷開(kāi)
socket.on('disconnect', () => {
console.log('客戶端斷開(kāi)')
})
// 給客戶端發(fā)送消息
socket.emit('welcome','歡迎連接socket')
// 監(jiān)聽(tīng)客戶端消息
socket.on('hello', data => {
console.log('接收客戶端發(fā)送數(shù)據(jù)', data)
})
});
服務(wù)端總結(jié)
服務(wù)端接收和發(fā)送消息和客戶端對(duì)調(diào)的,客戶端emit
發(fā)送消息,那么服務(wù)端這里就要on
監(jiān)聽(tīng)客戶端發(fā)送的消息亭螟,服務(wù)的發(fā)送同理挡鞍。
踩坑
訂閱事件記得要取消
socket主要還是用來(lái)寫(xiě)聊天室,加入socket房間后要訂閱房間內(nèi)所有的聊天內(nèi)容预烙,這時(shí)如果沒(méi)有取消之前的訂閱事件墨微,下次進(jìn)入會(huì)多次訂閱消息。也就是別人只發(fā)一條消息扁掸,你這邊接收到的卻是兩條甚至多條翘县。哪如何取消訂閱呢,我的處理方式是在離開(kāi)當(dāng)前聊天頁(yè)面后谴分,自動(dòng)取消之前所有的訂閱事件锈麸。
beforeDestroy() {
this.sockets.unsubscribe(eventName)
}
同理,如果是有指定頁(yè)面才加入socket房間牺蹄,退出頁(yè)面時(shí)也要記得關(guān)閉socket連接忘伞。比如你在created
中開(kāi)始連接socket,在beforeDestroy
要記得關(guān)閉socket沙兰,不然下次進(jìn)入也會(huì)連接socket氓奈。
created() {
this.$socket.open()
// 查看socket是否連接成功
this.$socket.connected
}
beforeDestroy() {
this.$socket.close()
}
Type Error: this.sockets.subscribe is not a function
這是我最近遇到的問(wèn)題,原本以為是自己的this指向有問(wèn)題僧凰,然后從到尾查遍了整個(gè)邏輯this探颈,發(fā)現(xiàn)并不是這個(gè)問(wèn)題。
在打印this.sockets
之后我發(fā)現(xiàn)問(wèn)題
subscribe
訂閱事件并沒(méi)有直接存在训措,而是某個(gè)對(duì)象的屬性,于是嘗試了一下this.sockets.listenner.subscribe
發(fā)現(xiàn)能用了光羞。
你以為這就結(jié)束了绩鸣??纱兑?接著我又發(fā)現(xiàn)問(wèn)題
sockets:{
welcome: data => {
console.log('welcome data ', data)
}
}
并且訂閱的事件中呀闻,socket日志顯示component: undefined
沒(méi)有看到數(shù)據(jù)
全局的訂閱事件沒(méi)有生效,并且socket自帶的連接事件也沒(méi)有啟動(dòng)打印潜慎。我直接傻了??捡多,之前使用的時(shí)候還沒(méi)有這些問(wèn)題,百度一大堆無(wú)果后铐炫,開(kāi)始像官方求助垒手。于是找到了問(wèn)題。
Vue-Socket.io: #connect subscribe, component: undefined
大概的意思是說(shuō)倒信,出現(xiàn)問(wèn)題的都是3.0.9的版本科贬,將版本后可以解決這個(gè)問(wèn)題。這也是我為啥要把socket服務(wù)端寫(xiě)進(jìn)了的原因鳖悠。自己本地寫(xiě)了一個(gè)小demo后榜掌,還真的是版本的問(wèn)題优妙,隨后就有了這篇文章。
總結(jié)
同學(xué)們?cè)谑褂胿ue-socket.io時(shí)要注意一下版本憎账,現(xiàn)在的3.0.9
多多少少會(huì)出現(xiàn)問(wèn)題套硼,可以選擇3.0.7
版本。這個(gè)可以使用文章開(kāi)頭我的測(cè)試demo進(jìn)行查看胞皱,socket服務(wù)代碼也在項(xiàng)目中熟菲。
第一次在掘金中發(fā)表文章,表達(dá)有錯(cuò)誤的地方還請(qǐng)多多諒解朴恳,之后也會(huì)發(fā)布更多前端技術(shù)文章抄罕,還請(qǐng)多多關(guān)注。