前奏
這篇文章僅對不熟悉在react中使用socket.io的人、以及websocket入門者有幫助。
下面這個動態圖展示的聊天系統是用react+express+websocket搭建的,很模糊吧,要得就是這樣的效果,我自己開了2個窗口,創建2個用戶自問自答。沒有什么高深的技術,對於很多想接觸websocket的前端工程師來說,不擅長后端的websocket代碼可能是硬傷。
開發環境
服務端:express服務器
客戶端:react技術棧,開發環境采用前端服務器的方式,打包后將靜態資源放到服務端目錄下做測試。
基本介紹
想要實現一種實時的雙向通信聊天系統,你可能會想到ajax輪詢(長或短),但你最想要的還是websocket的實現。
在寫測試代碼之前,我糾結於前端用什么,后端用什么,后來后端選擇了express、前端是react。
1、服務端使用到的js庫
express
socket.io
2、前端使用到的js庫
"react": "^16.2.0",
"react-dom": "^16.2.0",
"socket.io-client": "^2.0.4"
express服務端的實現
服務端的實現我不想多講,你可以去看官方demo,代碼很詳細:socket官方demo實現
服務端的核心代碼:
io.on('connection', function (socket) {
// 當客戶端發出“new message”時,服務端監聽到並執行相關代碼
socket.on('new message', function (data) {
// 廣播給用戶執行“new message”
socket.broadcast.emit('new message', {});
});
// 當客戶端發出“add user”時,服務端監聽到並執行相關代碼
socket.on('add user', function (username) {
socket.username = username;
//服務端告訴當前用戶執行'login'指令
socket.emit('login', {});
});
// 當用戶斷開時執行此指令
socket.on('disconnect', function () {});
});
socket和mongodb有點像,它需要創建一個socket服務,創建成功之后,就可以通過on()去監聽一個action,action在這里表示的是 'new message'、'add user'、'login'等指令,這些指令是可以自己命名的。
這些指令有什么作用呢?
當客戶端和服務端建立socket通信之后,服務端可以向客戶端發出指令,客戶端也可以向服務端發出指令,開發者需要先給雙方的通信約定一套指令系統。
比如服務端創建了一個 'new message'的指令,但是客戶端沒有創建這個指令,就會導致客戶端無法接收到服務端發出的這個指令。客戶端心里可能在想:服務端老兄在瞎bb什么?
客戶端也需要 ’new message’指令,這樣雙方就能達成一套通信的協議,雙方可以互相發出這條指令告訴對方最新的狀態。
上面代碼提到了socket.emit()和socket.broadcast.emit()2種用法,可以看看下面關於emit用法的詳細解釋。
// 發送到當前請求socket通信的客戶端
socket.emit('message', "this is a test");
// 發送給所有客戶端,除了發件人
socket.broadcast.emit('message', "this is a test");
// 發送給“游戲”房間(頻道)中的所有客戶,發件人除外
socket.broadcast.to('game').emit('message', 'nice game');
// 發送給所有的客戶,包括發件人
io.sockets.emit('message', "this is a test");
// 發送給“游戲”房間(頻道)的所有客戶,包括發件人
io.sockets.in('game').emit('message', 'cool game');
// 發送給指定的socketid
io.sockets.socket(socketid).emit('message', 'for your eyes only');
socket的這種行為更像是redux,但是redux是單向數據流,而socket是雙向。
React客戶端的實現
React端的實現,才是我們應該關注的重點。
作為一個前端工程師,往往只需要和后端大神配合即可(全棧除外)。
1、在react組件中導入socket.io-client
前端使用的是socket.io-client庫,這個庫使用非常簡單。下面的代碼中,直接導入socket.io-client並且指向服務端的ip+端口即可。
import React, { Component } from 'react'
//require('socket.io-client')('服務端ip+端口')
const socket = require('socket.io-client')('http://localhost:3077');
class App extends Component {
}
2、在componentDidMount寫socket的接收指令action
socket.on()設置了服務端約定好的指令,當服務端發出這些指令時,客戶端就能接收到。這時候,你可以在回調函數里面根據后端返回的數據 data 做前端的處理,比如設置state的狀態,渲染服務端推送的數據。
componentDidMount() {
socket.on('login', (data) => {
console.log(data)
});
socket.on('add user', (data) => {
console.log(data)
});
socket.on('new message', (data) => {
console.log(data)
});
}
3、客戶端推送數據到服務端
很多時候,客戶端也需要告訴服務端有新的數據更新,當你在聊天界面發了一條新消息,這時候要告訴服務端,就通過socket.emit()方法,和服務端推送的方法是一樣的。
socket.emit('new message', value)
總結
1、當你想要告訴對方一些話時,使用socket.emit()。
2、當你想接收對方的話時,使用socket.on()。
3、emit還有點對點、廣播等用法。
4、最后說一句,這些都是基礎知識。