Node.js使用socket.io时出现ReferenceError变量未定义及返回null问题求解
Node.js Socket.IO变量访问异常问题解决
问题核心
你遇到的报错和返回异常问题,本质是变量作用域和Node.js异步执行逻辑两个常见问题共同导致的,以下是各版本代码的问题分析和正确实现原则:
各版本代码问题拆解
1. 初始报错代码(ReferenceError: b is not defined)
var io = require('socket.io')(serv,{}); io.sockets.on('connection', function(socket){ console.log('new connection!'); socket.on('clntMsg',function(data){ var b = eval(data); console.log(data); return b; }); }); var a = b % 3;
报错原因:
b在clntMsg事件的回调函数内部用var声明,属于函数局部变量,仅在该回调内部可访问,外部代码完全无法识别该变量- 最外层的
var a = b % 3是同步执行代码,服务启动时就会运行,而clntMsg回调只有客户端发送对应消息时才会异步触发,运行到这行代码时b还未被定义 - 异步回调的
return b没有实际作用,事件触发机制不会接收异步回调的返回值,外层代码无法通过这种方式拿到b的值
2. 可正常运行的调整后代码
var io = require('socket.io')(serv,{}); var b var a io.sockets.on('connection', function(socket){ console.log('new connection!'); //var a = b % 3; socket.on('clntMsg',function(data){ b = eval(data); a = b % 3; console.log(data); socket.emit('serverMsg',{ msg:(a), }); }); });
运行正常的原因:
- 将
b、a提升到外层作用域声明,回调内部可以直接修改这两个变量的值 - 把依赖
b的计算逻辑a = b % 3和返回给客户端的socket.emit操作,都放到了clntMsg回调内部,保证执行时b已经被客户端传来的data赋值,执行顺序符合预期
3. 客户端返回null的错误代码
var io = require('socket.io')(serv,{}); var b io.sockets.on('connection', function(socket){ console.log('new connection!'); socket.on('clntMsg',function(data){ b = eval(data); console.log(data); }); socket.emit('serverMsg',{ msg:(a), }); }); var a = b % 3;
返回异常的原因:
- 最外层的
var a = b % 3仍是同步执行代码,服务启动时b仅声明未赋值,值为undefined,计算后a的值为NaN,后续clntMsg回调给b赋值时,a不会自动重新计算 socket.emit放在了clntMsg回调外部,属于connection事件的同步执行代码,客户端刚连接成功就会执行,此时还未收到客户端发送的clntMsg消息,b未赋值,返回给客户端的msg自然是无效值
正确实现核心原则
- 所有依赖socket事件返回数据的计算、返回逻辑,必须放到对应事件的回调函数内部执行,确保执行时数据已经被正确赋值
- 不建议用全局变量存储跨回调的临时值,多客户端连接场景下全局变量会被不同客户端的消息覆盖,建议直接在回调内部处理完所有逻辑,避免变量污染
- 禁止直接使用
eval处理客户端传来的任意数据,存在严重的代码注入风险,客户端可传入恶意代码在服务端执行,建议替换为JSON.parse或其他安全的解析方式
内容的提问来源于stack exchange,提问作者Renvo
相关产品推荐
相关产品推荐

