如何通过Express API将会话特定数据从服务器传递到客户端渲染
解决WebSocket聊天模块中传递用户名到客户端JS的问题
你当前的核心问题是:静态JS文件(chat.js)不会被Express模板引擎解析,所以直接写{{ username }}只会被当作纯字符串输出,无法获取到真实的会话用户名。下面提供几个实用的解决思路:
方法1:在HTML页面嵌入全局变量(最简单方案)
因为chatPage.html是通过模板引擎渲染的,你可以在页面中添加一个script标签,把用户名挂载到window全局对象上,之后chat.js直接读取这个全局变量即可。
修改chatPage.html:
<script> // 把模板渲染后的用户名赋值给全局对象 window.currentUsername = '{{ username }}'; </script> <script defer src="http://localhost:3000/socket.io/socket.io.js"></script> <script defer src="chat.js"></script> <div class="message-container" id="message-container"></div> <form id="send-container"> <input type="text" id="message-input"> <button type="submit" id="send-button">Send</button> </form>
修改chat.js中的用户名获取逻辑:
const name = window.currentUsername; // 后续代码保持不变
方法2:将JS文件改为模板文件,由Express渲染输出
如果不想用全局变量,可以把chat.js改成模板文件(比如chat.js.ejs),让Express渲染后再返回给客户端。
- 将
chat.js重命名为chat.js.ejs,保留原代码中的const name = '{{ username }}'; - 在服务器端新增路由处理这个JS文件的请求:
app.get('/chat.js', (req, res) => { // 复用登录校验逻辑 isLoggedin(req, () => { res.setHeader('Content-Type', 'application/javascript'); res.render('chat.js.ejs', { username: req.session.account_username }); }, () => { res.redirect('/login'); }); });
- 修改HTML中的script引用:
<script defer src="/chat.js"></script>
方法3:服务器端通过Session直接获取用户名(最安全方案)
其实完全不需要客户端传递用户名——Socket.IO的连接可以关联到Express的Session,服务器端直接从Session中读取用户名即可,还能避免客户端伪造用户名的风险。
修改服务器端Socket.IO连接处理代码:
io.on('connection', (socket) => { // 从请求会话中直接获取用户名 const username = socket.request.session.account_username; // 将用户名绑定到socket对象,方便后续使用 socket.username = username; // 通知其他用户当前用户上线 socket.broadcast.emit('user-connected', username); socket.on('send-chat-message', (message) => { // 发送消息时直接用服务器端获取的用户名 socket.broadcast.emit('chat-message', { name: username, message: message }); }); socket.on('disconnect', () => { socket.broadcast.emit('user-disconnected', username); }); });
对应的chat.js可以去掉手动传递用户名的逻辑:
const socket = io('http://localhost:3000') const messageContainer = document.getElementById('message-container') const messageForm = document.getElementById('send-container') const messageInput = document.getElementById('message-input') appendMessage('You joined') // 无需再emit 'new-user',服务器端已通过Session获取用户名 socket.on('chat-message', data => { appendMessage(`${data.name}: ${data.message}`) }) socket.on('user-connected', name => { appendMessage(`${name} connected`) }) socket.on('user-disconnected', name => { appendMessage(`${name} disconnected`) }) messageForm.addEventListener('submit', e => { e.preventDefault() const message = messageInput.value appendMessage(`You: ${message}`) socket.emit('send-chat-message', message) messageInput.value = '' }) function appendMessage(message) { const messageElement = document.createElement('div') messageElement.innerText = message messageContainer.append(messageElement) }
内容的提问来源于stack exchange,提问作者dumpysmasher
相关产品推荐
相关产品推荐

