React, Node.js eveneming在快速路由到socket.io



我使用socket.io向客户端发送消息,我知道我可以使用快速路由的HTTP响应来完成此示例,但在实际场景中,当我从API获取数据时,我会发出。

然而,这个例子重复了我现在的问题:

当我单击客户端上的按钮时,我向快速路线发出get请求,我的意图是一旦我单击发出消息就会被记录,但是我必须双击才能打印消息。

server.js

import express from 'express'
import { createServer } from 'http'
import { Server } from 'socket.io'
import route from './route.js'
import { EventEmitter } from 'events'
const app = express()
const httpServer = createServer(app)
const io = new Server(httpServer, {
cors: true,
origins: [`http://locahost:4000}`]
})
const myEmitter = new EventEmitter()
app.use('/route', route)
app.set('event', myEmitter) // Attach the event emitter to use on routes
const connections = []
io.on('connection', (socket) => {
connections.push(socket)
console.log(`Socket id ${socket.id} connected`)
socket.on('disconnect', () => {
connections.splice(connections.indexOf(socket), 1)
})
})
// Socket.io emit generator on an EventEmitter listener
myEmitter.on('my-event', (data) => {
connections.forEach((socket) => {
socket.emit('notify', data)
})
})
httpServer.listen(4000, () => console.log(`App listening on port 4000.`))

route.js - Express route

import { Router } from 'express'
const router = Router()
router.get('/', async (req, res) => {
// Import the EventEmitter
const event = req.app.get('event')
// Here I send the string to the EventEmitter 
event.emit('my-event', 'Hello from route')
res.send({ ok: true })
})
export default router

Client - React函数在click事件中调用

// To get the message logged, I am having to run this function twice
const callRoute = () => {
// Initialize socket
const socket = socketIOClient('http://localhost:4000')
// I request the express route with axios
await axios('/route')
// Then I want to print the message
socket.on('notify', (data) => {
console.log(data)
})
}

我发现了问题,我只需要在客户端做一点改变:

不是在功能组件内部初始化套接字,而是必须在功能组件外部初始化套接字,然后使用useEffect侦听emit

// Declare it before the app
const socket = socketIOClient('http://localhost:4000')

// Main functional component
const App = () => {
// Here initialize the socket.io listener
useEffect(() => {
socket.on('notify', (data) => {
console.log(data)
})
}, [])
// Also disconnect if unmounts
useEffect(() => () => socket.disconnect(), [])
// And now I can connect to the route
const callRoute = () => {
await axios('/route')
}
....

另外,如果您想使用此设置向特定客户端发出,我很难找到,请这样做:

在客户端获取浏览器socket.id并将其置于状态

const [clientID, setClientID] = useState('')
useEffect(() => {
socket.on('connect', () => {
setClientID(socket.id)
})
socket.on('notify', (data) => {
console.log(data)
})
}, [])
// Then send the clientID to the route
const callRoute = () => {
await axios('/route', { params: { clientID } })
}

在路由上传递clientID

event.emit('my-event', { 
message: 'Hello from route', 
socketID: req.query.clientID 
})

在服务器端把你的发射器改成这个

myEmitter.on('my-event', (data) => {
io.to(data.socketID).emit('notify', data.message)
})

最新更新