跨平台实现实时通讯
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>
// 实例化 socket
const 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) return
console.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>