在下面的代碼中,我假設我的路由處理程式io有可能在建立連接之前觸發并嘗試發送到套接字:
服務器.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)
})
})
客戶端.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)
})
})
或者這是不推薦的并且有更好的選擇?
uj5u.com熱心網友回復:
把app.post()和app.get()里面io.on('connection', ...)是永遠正確的設計和實施。這是因為io.on('connection', ...)被多次觸發,并且一遍又一遍地添加相同的快速路由處理程式是沒有意義的,因為這只會浪費記憶體而沒有任何用處。在 socket.io 上連接的第一個客戶端會導致路由被注冊,并且從那時起它們將用于所有其他客戶端(無論它們是否通過 socket.io 連接)。
目前還不清楚你為什么要這樣做。您不會為一種特定情況安裝路由。為所有州的所有客戶端安裝一次路由。因此,如果您嘗試有條件地安裝路由,則這種型別的設計不起作用。如果您進一步解釋您要實作的目標,那么也許我們可以為設計提出一些不同的建議。
在下面的代碼中,我假設我的路由處理程式有可能在建立 io 連接之前觸發并嘗試發送到套接字:
app.post('/something', (req, res) => {
req.app.io.emit('something', doSomethingWith(req.body))
res.status(200)
});
這段代碼的具體作業方式取決于 POST 的內容。如果它是現有頁面中的 Javascript,那么該頁面將已經啟動并初始化,并且您可以控制(使用頁面中的 Javascript 客戶端代碼)是否等待/something在 socket.io 連接建立之后發出 POST 。
如果此 POST 是基于瀏覽器的常規表單提交(不涉及 Javascript),那么您會遇到其他問題,因為來自瀏覽器的表單提交會使用 POST 的回應重新加載當前瀏覽器頁面,并且在重新加載頁面的程序中,殺死該頁面具有的任何現有 socket.io 連接(因為它加載了一個新頁面)。由于您沒有從 POST 發回任何內容,這將導致瀏覽器中顯示一個空頁面并且沒有 socket.io 連接。
在查看您的客戶端代碼時,似乎 POST 來自fetch()客戶端代碼中的 a(因此完全基于 Javascript)。如果是這種情況,我建議重構您的客戶端代碼,以便它等待 socket.io 連接完成連接,然后再執行fetch(). 這樣,您知道您將能夠接收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', ....)
});
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/355653.html
