使用 ws 发送自定义事件

Posted

技术标签:

【中文标题】使用 ws 发送自定义事件【英文标题】:Send a custom event with ws 【发布时间】:2021-02-21 15:53:56 【问题描述】:

我正在尝试使用本机 websockets 并在后端使用 ws 在客户端上侦听自定义事件。

我首先创建一个连接的客户端池。

import express from 'express'
import http from 'http'
import WebSocket from 'ws'
import  v4 as uuidv4  from 'uuid'
import processes from './routes/process.js'
import  EventEmitter  from 'events'

// Express
const app = express()

// Initialize a simple http server
const server = http.createServer(app)

// Initialize the WebSocket server instance
const wss = new WebSocket.Server( server )

let connections = 

wss.on('connection', (socket) => 
  socket.id = uuidv4()
  connections[socket.id] = socket
  socket.send(socket.id)

  console.log(`Client connected ID: $socket.id`)

  socket.on('close', () => 
    delete connections[socket.id]
    delete socket.id
  )
)

在反应时我存储socketID

const [socketID, setSocketID] = useState('')

useEffect(() => 
  const socket = new WebSocket('ws://localhost:4000')
  socket.onmessage = (message) => setSocketID(message.data)
, [])

然后我想做的是使用 socketID 向特定客户端发出消息,我使用来自 react 的 axios 将请求中的 socketID 发送到快速路由。

然后回到服务器我使用EventEmitter从路由中获取客户端ID,我省略了细节原因有点冗长,但此时服务器正确识别客户端,问题似乎与发送自定义事件。

connections[socketID].send('notify', 'Hello specific client')

在客户端我监听自定义的nofify 事件

useEffect(() => 
  const socket = new WebSocket('ws://localhost:4000')
  socket.onmessage = (message) => setSocketID(message.data)
  // Set notify listener to notify this specific client only
  socket.addEventListener('notify', (data) => 
    // I am expecting 'Hello specific client'
    console.log(data)
  )
, [])

当我检查反应开发工具时,我可以看到 socketID 正在接收“自定义事件”,并将 socketID 更改为单词 notify。很明显,ws 只是发送单词 notify,而不是作为自定义事件,而是作为普通消息,客户端接收为 onmessage 而不是 eventListener。

【问题讨论】:

【参考方案1】:

由于我在任何地方都找不到关于 ws 发送自定义事件的任何信息,我只是使用唯一的发送事件来完成所有操作,我在消息中附加了一个事件字符串以了解触发了哪个事件。

不理想,但它有效。如果有人能想到更好的方法,请告诉我。

wss.on('connection', (socket) => 
  socket.id = uuidv4()
  connections[socket.id] = socket
  socket.send(JSON.stringify( event: 'ID', id: socket.id ))

  console.log(`Client connected ID: $socket.id`)

  socket.on('close', () => 
    delete connections[socket.id]
    delete socket.id
  )
)

connections[socketID].send(
  JSON.stringify( event: 'notify', payload: 'Hello specific client'))
)
useEffect(() => 
  const socket = new WebSocket('ws://localhost:4000')

  socket.onmessage = (message) => 

    const data = JSON.parse(message.data)

    if (data.event === 'ID') 
      setSocketID(data.id)
    

    if (data.event === 'notify') 
      console.log(data.payload)
    
  

, [])

【讨论】:

这基本上就是我正在做的事情。我不知道还有什么方法可以实现它。不幸的是,似乎如果同时收到多条消息,它就不起作用 - 我为 data.event 分配了一个变量,然后用它做很多事情。因此,当第一条消息通过时,变量被赋予了它的值,但在函数完成运行之前,第二条消息为变量重新分配了一个新值。您知道如何将变量绑定到消息并在有新消息通过时阻止它发生变化吗?

以上是关于使用 ws 发送自定义事件的主要内容,如果未能解决你的问题,请参考以下文章

第44课 发送自定义事件(下)

第43课 发送自定义事件(上)

如何使用 Zapier 向 Facebook Pixel 发送自定义事件

GWT 自定义事件 - 向事件发送者注册接收者

如何将自定义参数与保留事件一起发送到 Firebase 分析

Qt发送事件与自定义事件