Socket.io接收方离线时emit方法无法执行报错问题求助
问题原因
报错是因为接收方离线后,你用来存储在线用户socket实例的clients对象中已经不存在该targetId对应的属性,clients[targetId]为undefined,尝试调用undefined.emit()就会抛出cannot read property emit of undefined的错误。
修复方案
你可以先判断目标用户是否在线,再执行emit操作,还可以补充离线消息的存储逻辑,等用户上线后再推送未读消息,修复后的代码如下:
socket.on('data', Accmsg => { const findRsvpAndUpdate = (result, callback) => { var value = summa.findOneAndUpdate( {$or:[{sourceId:Accmsg.sourceId,targetId:Accmsg.targetId},{sourceId: Accmsg.targetId,targetId: Accmsg.sourceId}]}, {receive:Accmsg.receive,give:Accmsg.give,sourceId:Accmsg.sourceId,targetId:Accmsg.targetId},{upsert: true,new:true}, function (error,results){ if (error) { callback(error); } else { callback(null, results); } }) } findRsvpAndUpdate(Accmsg, (error, result) => { if (error) { console.log(error); return; } console.log("The result is " + result); const targetId = Accmsg.targetId; // 先判断目标用户是否在线 if (clients[targetId]) { clients[targetId].emit('clientAccount', Accmsg); } else { // 可选:补充离线消息存储逻辑,存到MongoDB的离线消息表中 console.log(`用户${targetId}当前离线,消息已存入离线队列`); // 示例存储逻辑:offlineMsgCollection.insertOne({targetId, msg: Accmsg, createTime: Date.now()}) } }); });
额外优化建议
- 可以在用户上线的逻辑中,新增查询离线消息并批量推送的逻辑,确保离线期间的消息不会丢失
- 移除不必要的try catch语句,提前判断
clients[targetId]是否存在的写法比捕获异常性能更好,逻辑也更清晰
内容的提问来源于stack exchange,提问作者Navjot Aulakh
相关产品推荐
相关产品推荐

