How to safely attach WebSocket event handlers with async work
mainWebSocket route handlers must attach event handlers (like socket.on('message', ...) ) synchronously during the handler's execution. If you perform asynchronous work (like database lookups or authentication) before attaching the handler, incoming messages might arrive while the async work is pending, causing them to be silently dropped because no listener is yet active.
Best Practice:
- Initiate the async work synchronously (e.g., call a function that returns a Promise).
- Attach the
socket.on('message', ...)handler immediately. - Inside the message handler,
awaitthe previously initiated Promise to access the required data.
fastify.get('/*', { websocket: true }, (socket, request) => {
// 1. Start async work synchronously, returning a promise
const sessionPromise = request.getSession()
// 2. Attach handler synchronously
socket.on('message', async (message) => {
// 3. Await the data inside the handler
const session = await sessionPromise()
// do something with the message and session
})
})