跨平台实现实时通讯
WebSocket
WebSockets 是一种先进的技术。它可以在用户的浏览器和服务器之间打开交互式通信会话。你可以向服务器发送消息并接收事件驱动的响应,而无需通过轮询服务器的方式以获得响应,比较典型的应用场景就是即时通讯(聊天)系统。
原生用法:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>WebSocket 示例</title></head><body><script>// 实例化 socketconst ws = new WebSocket('wss://socketsbay.com/wss/v2/1/demo/')// 监听连接的建立ws.onopen = function (ev) {console.log('建立连接...')ws.send('Hello WebSockets!')}// 监听连接的断开ws.onclose = function (ev) {console.log('断开连接...')}// 监听 socket 服务器消息ws.onmessage = function (ev) {console.log('收到消息: ' + ev.data)}</script></body>
</html>
通过以上的示例只需要对 WebSocket 建立起这样在印象:
- 采用的是
wss://
协议 - 分为客户端和服务端
- 实现连续的、长时间的与服务器通信
然而 WebSocket 提供的只是通信底层的机制,结合业务通常需进行二次封装,其中比较流行就是 socket.io
Socket.IO库
Socket.IO 是基于 WebSocket 进行的二次封装,封装了更多的业务层面的逻辑,如身份认证等、事件驱动等。
注意:其实 Socket.IO 不仅仅是封装了 WebSocket,还有基于 Ajax 的长轮询机制,在不支持 WebSocket 的环境中会自动降级为基于 Ajax 的长轮询机制。
长轮询机制可以粗暴的理解为在一个定时器中不断的重复发 Ajax 请求,以实现与服务器实时通信的功能。
-
下载 socket.io.js
pnpm add socket.io
然后建立连接,在建立连接进需要传入参数和登录信息:
// https://consult-api.itheima.net
const socket: Socket = io('socket服务器地址', {auth: { token: 'Bearer ' + xxx },query: { orderId: 订单id },transports: ['websocket', 'polling'],timeout: 5000,})socket.on('connect', () => {// 建立连接成功console.log('连接建立成功')})socket.on('error', (event) => {// 错误异常消息console.log('出现错误')})socket.on('disconnect', () => {// 已经断开连接console.log('断开连接')})
auth
登录状态信息,即token
query
建立连接时传递的参数transports
建立连接时使用的协议timeout
超时设置
Socket.IO 是基于事件来实现数据通信的,事件的名称是由前后端商定好的。
例如:
- 历史消息,事件名称为
chatMsgList
- 即时消息,事件名称为
receiveChatMsg
在建立连接时服务端会通过 chatMsgList
传递历史数据,通过 on
方法进行监听来获取这些数据:
<!-- subpkg_consult/room/index.vue -->
<script setup>// 消息列表const messageList = ref<MsgItem[]>([])// 获取历史消息socket.on('chatMsgList', (res: MsgData) => {// 没有返回数据if (res.code !== 10000) returnconsole.log('历史消息:', res.data)// 提取列表数据res.data?.forEach(({ items }) => {// 追加到消息列表中messageList.value.push(...items!)})console.log('历史消息:', messageList.value)})</script>
uni-app 提供了大图查看图片的 API uni.previewImage :
<script setup>// 预览图片const onPreviewClick = (urls: string) => {uni.previewImage({urls})}</script>