socket.io |我应该将路由处理程序包装在 io.on('connection') 中吗?
socket.io | Should I wrap my route handlers inside io.on('connection')?
在下面的代码中,我假设我的路由处理程序有可能在 io
连接建立之前触发并尝试发送到套接字:
server.js:
import { Server } from 'socket.io'
....
....
const app = express()
const io = new Server(....)
app.io = io
app.post('/something', (req, res) => {
req.app.io.emit('something', doSomethingWith(req.body))
res.status(200)
})
io.on('connection', function(socket) {
console.log('socket connected')
socket.on('disconnect', (reason) => {
console.log('disconnected due to = ', reason)
})
})
client.js:
socket = io(`http://localhost:${port}`, { transports: ['websocket'] })
socket.on('something', (data) => {
doSomethingMoreWith(data)
})
fetch('/something', ....)
在那种情况下,这样做是否更安全:
io.on('connection', function(socket) {
app.post('/something', ....)
app.get('/something', ....)
.....
...
socket.on('disconnect', (reason) => {
console.log('disconnected due to = ', reason)
})
})
或者不建议这样做,有更好的选择吗?
将 app.post()
和 app.get()
放在 io.on('connection', ...)
中从来都不是正确的设计或实现。这是因为 io.on('connection', ...)
被多次触发,并且一遍又一遍地添加相同的快速路由处理程序毫无意义,因为这只会浪费内存并且无济于事。第一个连接到 socket.io 的客户端将导致路由被注册,并且从那时起它们将在那里用于所有其他客户端(无论他们是否通过 socket.io 连接)。
不清楚您为什么要这样做。您不会为一种特定情况安装路线。为所有州的所有客户安装一次路由。所以,如果你试图有条件地安装路由,那么这种设计是行不通的。如果你进一步解释你想要完成的事情,那么也许我们可以为设计提出一些不同的建议。
In the code below, I'm assuming there is a chance that my route handler will fire and try to emit to the socket before the io connection has been established:
app.post('/something', (req, res) => {
req.app.io.emit('something', doSomethingWith(req.body))
res.status(200)
});
此代码的具体工作方式取决于 POST 正在执行的操作。如果它是现有页面中的 Javascript,那么该页面将已经启动并初始化并且您可以控制(使用页面中的 Javascript 客户端代码)是否等待将 POST 发布到/something
直到建立 socket.io 连接之后。
如果此 POST 是常规的基于浏览器的表单提交(不涉及 Javascript),那么您还有其他问题,因为来自浏览器的表单提交会重新加载当前浏览器页面的响应从 POST 并在重新加载页面的过程中,终止该页面拥有的任何现有 socket.io 连接(因为它加载了新页面)。由于您没有从 POST 发回任何内容,这将导致浏览器中显示一个空白页面并且没有 socket.io 连接。
在查看您的客户端代码时,似乎 POST 可能来自客户端代码中的 fetch()
(因此完全基于 Javascript)。如果是这种情况,我会建议重组您的客户端代码,以便它在执行 fetch()
之前等到 socket.io 连接完成连接。这样,您就知道您将能够收到服务器所提供的 io.emit()
。
socket = io(`http://localhost:${port}`, { transports: ['websocket'] })
socket.on('something', (data) => {
doSomethingMoreWith(data)
});
socket.on('connect', () => {
// only issue fetch after socket.io connection is operational
fetch('/something', ....)
});
在下面的代码中,我假设我的路由处理程序有可能在 io
连接建立之前触发并尝试发送到套接字:
server.js:
import { Server } from 'socket.io'
....
....
const app = express()
const io = new Server(....)
app.io = io
app.post('/something', (req, res) => {
req.app.io.emit('something', doSomethingWith(req.body))
res.status(200)
})
io.on('connection', function(socket) {
console.log('socket connected')
socket.on('disconnect', (reason) => {
console.log('disconnected due to = ', reason)
})
})
client.js:
socket = io(`http://localhost:${port}`, { transports: ['websocket'] })
socket.on('something', (data) => {
doSomethingMoreWith(data)
})
fetch('/something', ....)
在那种情况下,这样做是否更安全:
io.on('connection', function(socket) {
app.post('/something', ....)
app.get('/something', ....)
.....
...
socket.on('disconnect', (reason) => {
console.log('disconnected due to = ', reason)
})
})
或者不建议这样做,有更好的选择吗?
将 app.post()
和 app.get()
放在 io.on('connection', ...)
中从来都不是正确的设计或实现。这是因为 io.on('connection', ...)
被多次触发,并且一遍又一遍地添加相同的快速路由处理程序毫无意义,因为这只会浪费内存并且无济于事。第一个连接到 socket.io 的客户端将导致路由被注册,并且从那时起它们将在那里用于所有其他客户端(无论他们是否通过 socket.io 连接)。
不清楚您为什么要这样做。您不会为一种特定情况安装路线。为所有州的所有客户安装一次路由。所以,如果你试图有条件地安装路由,那么这种设计是行不通的。如果你进一步解释你想要完成的事情,那么也许我们可以为设计提出一些不同的建议。
In the code below, I'm assuming there is a chance that my route handler will fire and try to emit to the socket before the io connection has been established:
app.post('/something', (req, res) => {
req.app.io.emit('something', doSomethingWith(req.body))
res.status(200)
});
此代码的具体工作方式取决于 POST 正在执行的操作。如果它是现有页面中的 Javascript,那么该页面将已经启动并初始化并且您可以控制(使用页面中的 Javascript 客户端代码)是否等待将 POST 发布到/something
直到建立 socket.io 连接之后。
如果此 POST 是常规的基于浏览器的表单提交(不涉及 Javascript),那么您还有其他问题,因为来自浏览器的表单提交会重新加载当前浏览器页面的响应从 POST 并在重新加载页面的过程中,终止该页面拥有的任何现有 socket.io 连接(因为它加载了新页面)。由于您没有从 POST 发回任何内容,这将导致浏览器中显示一个空白页面并且没有 socket.io 连接。
在查看您的客户端代码时,似乎 POST 可能来自客户端代码中的 fetch()
(因此完全基于 Javascript)。如果是这种情况,我会建议重组您的客户端代码,以便它在执行 fetch()
之前等到 socket.io 连接完成连接。这样,您就知道您将能够收到服务器所提供的 io.emit()
。
socket = io(`http://localhost:${port}`, { transports: ['websocket'] })
socket.on('something', (data) => {
doSomethingMoreWith(data)
});
socket.on('connect', () => {
// only issue fetch after socket.io connection is operational
fetch('/something', ....)
});