1.如何使用客户端js库?
pnpm add socket.io-client
2.如何建立连接?
import io from 'socket.io-client'
// 参数1:不传默认是当前服务域名,开发中传入服务器地址
// 参数2:配置参数,根据需要再来介绍
const socket = io()
3.如何确定连接成功?
socket.on('connect', () => {
// 建立连接成功
})
4.如何发送消息?
// chat message 发送消息事件,由后台约定,可变
socket.emit('chat message', '消息内容')
5.如何接收消息?
// chat message 接收消息事件,由后台约定,可变
socket.on('chat message', (ev) => {
// ev 是服务器发送的消息
})
6.如何关闭连接?
// 离开组件需要使用
socket.close()
- sockt.io 在前端使用的js库需要知道哪些内容?
- 如何建立链接
io('地址')
- 连接成功的事件
connect
- 如何发消息
emit
+ 事件 - 如何收消息
on
+ 事件 - 如果关闭连接
close()
- 如何建立链接
7.通讯规则
chatMsgList
接收聊天记录
sendChatMsg
发送消息
receiveChatMsg
接收消息
updateMsgStatus
消息已读
getChatMsgList
获取聊天记录
statusChange
接收订单状态改变
8.问诊室-建立连接
步骤:
- 安装 sokect.io-client 包
- 在组件挂载完毕,进行socket连接
- 监听连接成功,监听错误消息,监听关闭连接
- 组件卸载关闭连接
代码:
- 安装 sokect.io-client 包
pnpm add socket.io-client
import type { Socket } from 'socket.io-client'
import { io } from 'socket.io-client'
import { onMounted, onUnmounted } from 'vue'
import { baseURL } from '@/utils/request'
import { useUserStore } from '@/stores'
import { useRoute } from 'vue-router'
const store = useUserStore()
const route = useRoute()
let socket: Socket
onUnmounted(() => {
socket.close()
})
onMounted(async () => {
// 建立链接,创建 socket.io 实例
socket = io(baseURL, {
auth: {
token: `Bearer ${store.user?.token}`
},
query: {
orderId: route.query.orderId
}
})
socket.on('connect', () => {
// 建立连接成功
console.log('connect')
})
socket.on('error', (event) => {
// 错误异常消息
console.log('error')
})
socket.on('disconnect', ()=> {
// 已经断开连接
console.log('disconnect')
})
})
9.问诊室-默认消息
步骤:
- 监听默认聊天记录,并且处理处理成消息列表
- 提取常量数据
- 进行渲染
- 预览病情图片
代码:
1)监听默认聊天记录,并且处理处理成消息列表 Room/index.vue
import { MsgType } from '@/enums'
import type { Message, TimeMessages } from '@/types/room'
const list = ref<Message[]>([])
// 聊天记录
socket.on('chatMsgList', ({ data }: { data: TimeMessages[] }) => {
// 准备转换常规消息列表
const arr: Message[] = []
data.forEach((item, i) => {
arr.push({
msgType: MsgType.Notify,
msg: { content: item.createTime },
createTime: item.createTime,
id: item.createTime
})
arr.push(...item.items)
})
// 追加到聊天消息列表
list.value.unshift(...arr)
})
- 抽取常量数据
services/constants.ts
import { IllnessTime } from '@/enums'
export const timeOptions = [
{ label: '一周内', value: IllnessTime.Week },
{ label: '一月内', value: IllnessTime.Month },
{ label: '半年内', value: IllnessTime.HalfYear },
{ label: '大于半年', value: IllnessTime.More }
]
export const flagOptions = [
{ label: '就诊过', value: 0 },
{ label: '没就诊过', value: 1 }
]
3)进行渲染 Room/components/RoomMessage.vue
<room-message :list="list" />
import { IllnessTime } from '@/enums'
import { flagOptions, timeOptions } from '@/services/constants'
defineProps<{ list: Message[] }>()
const getIllnessTimeText = (time: IllnessTime) =>
timeOptions.find((item) => item.value === time)?.label
const getConsultFlagText = (flag: 0 | 1) =>
flagOptions.find((item) => item.value === flag)?.label
<template v-for="{ msgType, msg, createTime, from } in list" :key="msg.id">
<!-- 病情描述 -->
<div class="msg msg-illness" v-if="msgType === MsgType.CardPat">
<div class="patient van-hairline--bottom" v-if="msg.consultRecord">
<p>
{{ msg.consultRecord.patientInfo.name }}
{{ msg.consultRecord.patientInfo.genderValue }}
{{ msg.consultRecord.patientInfo.age }}岁
</p>
<p>
{{ getIllnessTimeText(msg.consultRecord.illnessTime) }} |
{{ getConsultFlagText(msg.consultRecord.consultFlag) }}
</p>
</div>
<van-row>
<van-col span="6">病情描述</van-col>
<van-col span="18">{{ msg.consultRecord?.illnessDesc }}</van-col>
<van-col span="6">图片</van-col>
<van-col span="18" @click="previewImg(msg.consultRecord?.pictures)"> 点击查看 </van-col>
</van-row>
</div>
<!-- 温馨提示 -->
<div class="msg msg-tip" v-if="msgType === MsgType.NotifyTip">
<div class="content">
<span class="green">温馨提示:</span>
<span>{{ msg.content }}</span>
</div>
</div>
<!-- 通用通知 -->
<div class="msg msg-tip" v-if="msgType === 31">
<div class="content">
<span>{{ msg.content }}</span>
</div>
</div>
</template>
总结
什么是Socket.IO
Socket.IO是一个库,可用于在浏览器和服务器之间进行实时,双向和基于事件的通信。它包括:
- 使Node.js服务器:来源 | API
- 为浏览器(可从Node.js的也运行)一个JavaScript客户端库:来源 | API
其主要特点是:
可靠性
即使存在以下情况,也会建立连接:
- 代理和负载平衡器。
- 个人防火墙和防病毒软件。
为此,它依赖于Engine.IO,该引擎首先建立长轮询连接,然后尝试升级到在侧面进行“测试”的更好传输,例如WebSocket。请参阅“ 目标”部分以获取更多信息。
自动重新连接支持
除非另有指示,否则断开连接的客户端将尝试永久重新连接,直到服务器再次可用为止。请在此处查看可用的重新连接选项。
断线检测
心跳机制在Engine.IO级别上实现,使服务器和客户端都可以知道对方何时不再响应。
通过在服务器和客户端上设置计时器,并在连接握手期间共享超时值(pingInterval和pingTimeout参数),可以实现该功能。这些计时器要求将任何后续客户端调用都定向到同一服务器,因此使用多个节点时需要执行粘性会话。
二进制支持
可以发出任何可序列化的数据结构,包括:
- 浏览器中的ArrayBuffer和Blob
- Node.js中的ArrayBuffer和Buffer
多路传输支持
为了在应用程序内创建关注点分离(例如,每个模块或基于权限),Socket.IO允许您创建多个Namespaces,它们将充当单独的通信通道,但将共享相同的基础连接。
客房支援
在每个Namespace中,您可以定义套接字可以加入和离开的任意通道,称为Rooms。然后,您可以广播到任何给定的房间,到达已加入该房间的每个插槽。
这是有用的功能,用于向一组用户或连接到多个设备的给定用户发送通知。
这些功能附带一个简单便捷的API,如下所示:
io.on('connection',function(socket) {
socket.emit('request',/ * * /); //向套接字发出事件
io.emit('broadcast',/ * * /); / /向所有连接的套接字发出事件
socket.on('reply',function() { / * * / }); //监听事件
});
什么不是Socket.IO
Socket.IO 不是 WebSocket实现。尽管Socket.IO确实确实在可能的情况下使用WebSocket作为传输工具,但它会向每个数据包添加一些元数据:当需要消息确认时,数据包类型,名称空间和数据包ID。这就是为什么WebSocket客户端将无法成功连接到Socket.IO服务器,而Socket.IO客户端也将无法连接到WebSocket服务器的原因。请在此处查看协议规范。
//警告:客户端将无法连接!
const client = io('ws://echo.websocket.org');
安装
npm install --save socket.io
Javascript客户端
默认情况下,服务器会公开客户端的独立版本/socket.io/socket.io.js
。
也可以从CDN提供服务,例如cdnjs。
若要从Node.js的使用就像一个捆绑使用,或的WebPack或browserify,您还可以安装NPM包:
npm install-save socket.io-client
其他客户端实施
有几种其他语言的客户端实现,由社区维护:
- Java:https://github.com/socketio/socket.io-client-java
- C ++:https://github.com/socketio/socket.io-client-cpp
- 斯威夫特:https : //github.com/socketio/socket.io-client-swift
- 飞镖:https://github.com/rikulo/socket.io-client-dart
- Python:https://github.com/miguelgrinberg/python-socketio
- .Net:https://github.com/Quobject/SocketIoClientDotNet
与Node http服务器一起使用
服务器(app.js)
var app = require('http').createServer(handler)
var io = require('socket.io')(app);
var fs = require('fs');
app.listen(80);
function handler (req, res) {
fs.readFile(__dirname + '/index.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
io.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io('http://localhost');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
</script>
与Express一起使用
服务器(app.js)
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
server.listen(80);
// WARNING: app.listen(80) will NOT work here!
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
客户端(index.html)
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
</script>
发送和接收事件
Socket.IO允许您发射和接收自定义事件。此外connect
,message
和disconnect
,你可以发出自定义事件:
服务器
// note, io(<port>) will create a http server for you
var io = require('socket.io')(80);
io.on('connection', function (socket) {
io.emit('this', { will: 'be received by everyone'});
socket.on('private message', function (from, msg) {
console.log('I received a private message by ', from, ' saying ', msg);
});
socket.on('disconnect', function () {
io.emit('user disconnected');
});
});
如果您可以控制为特定应用程序发出的所有消息和事件,则可以使用默认值/命名空间。如果您想利用第三方代码或生成与他人共享的代码,socket.io提供了一种命名套接字的方式。
这具有multiplexing
单个连接的优点。不是使用两个WebSocket
连接,而是使用一个连接。
服务器(app.js)
var io = require('socket.io')(80);
var chat = io
.of('/chat')
.on('connection', function (socket) {
socket.emit('a message', {
that: 'only'
, '/chat': 'will get'
});
chat.emit('a message', {
everyone: 'in'
, '/chat': 'will get'
});
});
var news = io
.of('/news')
.on('connection', function (socket) {
socket.emit('item', { news: 'item' });
});
客户端(index.html)
<script>
var chat = io.connect('http://localhost/chat')
, news = io.connect('http://localhost/news');
chat.on('connect', function () {
chat.emit('hi!');
});
news.on('news', function () {
news.emit('woot');
});
</script>
发送易失性消息
有时可能会丢弃某些消息。假设您有一个应用程序可显示关键字的实时推文bieber
。
如果某个客户端尚未准备好接收消息(由于网络速度慢或其他问题,或者由于它们是通过长时间轮询连接的,并且处于请求-响应周期的中间),则它没有接收到所有推文与bieber相关,您的应用程序不会受到影响。
在这种情况下,您可能希望将这些消息作为易失性消息发送。
服务器
var io = require('socket.io')(80);
io.on('connection', function (socket) {
var tweets = setInterval(function () {
getBieberTweet(function (tweet) {
socket.volatile.emit('bieber tweet', tweet);
});
}, 100);
socket.on('disconnect', function () {
clearInterval(tweets);
});
});
发送和获取数据(确认)
有时,当客户端确认消息接收后,您可能希望获得回调。
为此,只需将函数作为.send
或的最后一个参数传递即可.emit
。而且,当您使用时.emit
,确认是由您完成的,这意味着您还可以传递数据:
服务器(app.js)
var io = require('socket.io')(80);
io.on('connection', function (socket) {
socket.on('ferret', function (name, word, fn) {
fn(name + ' says ' + word);
});
});
客户端(index.html)
<script>
var socket = io(); // TIP: io() with no args does auto-discovery
socket.on('connect', function () { // TIP: you can avoid listening on `connect` and listen on events directly too!
socket.emit('ferret', 'tobi', 'woot', function (data) { // args are sent in order to acknowledgement function
console.log(data); // data will be 'tobi says woot'
});
});
</script>
广播消息
要广播,只需broadcast
在emit
和send
方法调用中添加一个标志。广播意味着将消息发送到其他人(除了启动该消息的套接字之外)。
服务器
var io = require('socket.io')(80);
io.on('connection', function (socket) {
socket.broadcast.emit('user connected');
});
像跨浏览器的WebSocket一样使用它
如果只需要WebSocket语义,也可以这样做。只需利用send
并收听message
事件:
服务器(app.js)
var io = require('socket.io')(80);
io.on('connection', function (socket) {
socket.on('message', function () { });
socket.on('disconnect', function () { });
});
客户端(index.html)
<script>
var socket = io('http://localhost/');
socket.on('connect', function () {
socket.send('hi');
socket.on('message', function (msg) {
// my msg
});
});
</script>
如果不关心此类的重新连接逻辑,请查看Engine.IO,这是Socket.IO使用的WebSocket语义传输层。
项目应用源码参考:lien0219/consult-patient-h5: 在线医疗h5项目,可以在线问诊,使用vue3+ts+pinia+websocket技术栈,项目包含第三方授权登录,订单支付,暂时支持支付宝支付,问诊咨询即时通讯等技术 (github.com)