websocket消息支持 (#188)
* Release (#162) * feat: ✨ websocket server demo * feat: ✨ ws server demo dev * feat: ✨ ws server and mobile page * feat: ✨ 手机端发送消息 * feat: ✨ 手机网页发送消息 * 添加了抽奖中和抽奖完成时的音效 * feat: ✨ 自定义设置弹幕服务器地址 * feat: ✨ ws not done * fix: 🐛 fix pr-185 #185 为播放音效添加控制 * feat: ✨ server worker demo not done * feat: ✨ websocket server * feat: ✨ 全局接收websocket消息并存储到indexdb中 --------- Co-authored-by: Silence@2024 <707261624@qq.com>
This commit is contained in:
28
src/hooks/useTimerWorker/index.ts
Normal file
28
src/hooks/useTimerWorker/index.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { onUnmounted } from 'vue'
|
||||
import TimerWorker from './timerWorker.ts?worker'
|
||||
|
||||
export function useTimerWorker(interval: number) {
|
||||
let timerWorker: Worker | null = null
|
||||
const init = (callback: () => void) => {
|
||||
close()
|
||||
timerWorker = new TimerWorker()
|
||||
timerWorker.postMessage({ interval })
|
||||
if (timerWorker.onmessage)
|
||||
return
|
||||
timerWorker.addEventListener('message', () => callback())
|
||||
}
|
||||
|
||||
function close() {
|
||||
timerWorker?.terminate()
|
||||
timerWorker = null
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
close()
|
||||
})
|
||||
|
||||
return {
|
||||
init,
|
||||
close,
|
||||
}
|
||||
}
|
||||
12
src/hooks/useTimerWorker/timerworker.ts
Normal file
12
src/hooks/useTimerWorker/timerworker.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
let intervalId: number | null = null
|
||||
self.addEventListener('message', (e) => {
|
||||
const { interval } = e.data
|
||||
if (!interval)
|
||||
throw new Error('invalid params')
|
||||
if (intervalId)
|
||||
clearInterval(intervalId)
|
||||
intervalId = setInterval(() => {
|
||||
self.postMessage(true)
|
||||
}, interval)
|
||||
})
|
||||
114
src/hooks/useWebsocket.ts
Normal file
114
src/hooks/useWebsocket.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
import type { IMsgType } from '@/types/msgType'
|
||||
import type { WsMsgData } from '@/types/storeType'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { useTimerWorker } from './useTimerWorker'
|
||||
|
||||
export function useWebsocket() {
|
||||
const { init: initWorker, close: closeWorker } = useTimerWorker(30 * 1000)
|
||||
const status = ref<{ status: WebSocket['readyState'], connected: boolean }>()
|
||||
const data = ref<WsMsgData>()
|
||||
const registration = ref<ServiceWorkerRegistration | null>(null)
|
||||
async function registerSW() {
|
||||
if ('serviceWorker' in navigator) {
|
||||
try {
|
||||
registration.value = await navigator.serviceWorker.register('/log-lottery/sw.js')
|
||||
console.log('Service Worker 注册成功:', registration)
|
||||
listenSWMessage()
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Service Worker 注册失败:', error)
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.error('浏览器不支持 Service Worker')
|
||||
}
|
||||
}
|
||||
|
||||
function open(url: string) {
|
||||
navigator.serviceWorker.ready.then((registration) => {
|
||||
registration.active?.postMessage({
|
||||
type: 'CONNECT_WS',
|
||||
payload: { url },
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function close() {
|
||||
closeWorker()
|
||||
navigator.serviceWorker.ready.then((registration) => {
|
||||
registration.active?.postMessage({
|
||||
type: 'DISCONNECT_WS',
|
||||
})
|
||||
})
|
||||
}
|
||||
function send(message: string) {
|
||||
navigator.serviceWorker.ready.then((registration) => {
|
||||
registration.active?.postMessage({
|
||||
type: 'SEND_WS_MESSAGE',
|
||||
payload: { message, id: uuidv4() },
|
||||
})
|
||||
})
|
||||
}
|
||||
function getStatus() {
|
||||
navigator.serviceWorker.ready.then((registration) => {
|
||||
registration.active?.postMessage({
|
||||
type: 'GET_WS_STATUS',
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 监听service worker消息
|
||||
function listenSWMessage() {
|
||||
navigator.serviceWorker.addEventListener('message', (event) => {
|
||||
const msgType = event.data.type
|
||||
switch (msgType) {
|
||||
case 'WS_STATUS':
|
||||
status.value = event.data.payload
|
||||
break
|
||||
case 'WS_MESSAGE':{
|
||||
const receivedMsg: IMsgType = event.data.payload as IMsgType
|
||||
data.value = {
|
||||
...receivedMsg,
|
||||
id: uuidv4(),
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'WS_ERROR':
|
||||
console.error('ws error:', event.data.payload)
|
||||
status.value = {
|
||||
status: WebSocket.CLOSED,
|
||||
connected: false,
|
||||
}
|
||||
closeWorker()
|
||||
break
|
||||
case 'WS_CLOSE':
|
||||
status.value = {
|
||||
status: WebSocket.CLOSED,
|
||||
connected: false,
|
||||
}
|
||||
closeWorker()
|
||||
break
|
||||
case 'WS_OPEN':
|
||||
status.value = {
|
||||
status: WebSocket.OPEN,
|
||||
connected: true,
|
||||
}
|
||||
initWorker(getStatus)
|
||||
break
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
registerSW()
|
||||
getStatus()
|
||||
})
|
||||
return {
|
||||
open,
|
||||
close,
|
||||
send,
|
||||
status,
|
||||
data,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user