You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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渲染后再返回给客户端。

  1. 将chat.js重命名为chat.js.ejs,保留原代码中的const name = '{{ username }}';
  2. 在服务器端新增路由处理这个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');
  });
});
  1. 修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 20:52:02