Node.js WebSocket中连接级player持久变量赋值后不生效问题排查
问题分析:WebSocket连接中player变量无法持久化的原因
你遇到的问题核心是JavaScript的参数传递机制导致的——基本类型(比如字符串、数字)是按值传递,而非引用传递。
先还原你的场景:你在每个WebSocket连接的回调里定义了player变量,调用HandleRoomEnter试图修改它,但后续调用HandleReadyness时,player还是初始的"none",输出结果如下:
setting: Conan
getting: none
具体原因解释
当你把player作为参数传给HandleRoomEnter函数时,函数内部拿到的只是"none"这个字符串的副本,而不是指向外层player变量的引用。所以在HandleRoomEnter里对player的赋值操作,只会修改这个局部的副本,完全不会影响到外层作用域里的player变量。这就是为什么后续HandleReadyness拿到的还是原来的"none"。
两种可行的解决方案
方案1:用对象包裹player(利用引用传递特性)
因为JavaScript中对象是按引用传递的,把player放在一个对象里,函数拿到的是这个对象的引用,修改对象的属性就能直接影响到外层的变量:
Server.on('request', function(request) { const WSCon = request.accept(null, request.origin); // 用对象包裹player,保存引用 const player = { name: "none" }; WSCon.on('message', function(message) { // 注意:需要先解析WebSocket消息为可用的data对象 const data = JSON.parse(message.utf8Data); if (data.action === 0) HandleRoomEnter(player); if (data.action === 1) HandleReadyness(player); }); }); function HandleRoomEnter(player) { player.name = "Conan"; console.log("setting: "+player.name); } function HandleReadyness(player) { console.log("getting: "+player.name); }
方案2:让函数返回修改后的值,在外层重新赋值
这种方式更直接,让HandleRoomEnter返回修改后的player值,在外层的回调里把返回值重新赋值给player变量:
Server.on('request', function(request) { const WSCon = request.accept(null, request.origin); let player = "none"; WSCon.on('message', function(message) { const data = JSON.parse(message.utf8Data); if (data.action === 0) { // 接收函数返回的新值,更新外层的player player = HandleRoomEnter(player); } if (data.action === 1) HandleReadyness(player); }); }); function HandleRoomEnter(player) { player = "Conan"; console.log("setting: "+player); // 返回修改后的值 return player; } function HandleReadyness(player) { console.log("getting: "+player); }
额外提醒
原代码里缺少了WebSocket消息的解析步骤(data变量没有定义),实际运行时需要先把消息内容解析成JSON对象,不然会出现data is undefined的错误,上面的示例里已经补充了这部分代码。
内容的提问来源于stack exchange,提问作者Lukáš Michalec
相关产品推荐
相关产品推荐

