簡體   English   中英

反應,Node.js EvenEmitting 在快速路由到 socket.io

[英]React, Node.js EvenEmitting on Express route to socket.io

我正在使用socket.io向客戶端發送消息,我知道我可以使用HTTP響應形式的快速路由來完成此示例,但在實際場景中,當我從 ZDB974238714CA8DE634A7CED14F 獲取數據時,我會發出

然而,這個例子復制了我現在遇到的問題:

當我單擊客戶端上的按鈕時,我向快速路由發出獲取請求,我的意圖是在單擊后立即記錄發出消息,但我必須雙擊才能打印消息。

服務器.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 - 快速路線

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

客戶端 - 在點擊事件上調用 React function

// 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來監聽發射

// 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並將其放在 state

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)
})

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM