0x00 发现问题
今天在写聊天室的过程中,遇到一个匪夷所思的问题,当时真是一脸懵逼,检查了好几遍都没问题,而且奇怪的是,只要刷新一下就恢复正常。搞得我差点设置在切换后自动刷新了。当然,这样用户体验很不好,所以静下心来找答案。
问题:当切换房间后,无法添加聊天记录
切换房间有两种方式:
1. 先跳转到房间选择页面,再选择一个房间
2. 直接跳转到一个房间
这种问题看起来就像是切了房间就不能发送消息了,而且两个都出了问题,真是头大。。。
0x01 试错过程
1. 客户端到底有没有发送出数据
首先,看看server端输出调试信息,确定发送没问题。
客户连接,断开连接,加入房间都输出了调试消息。
已经在某房间:71ee20ff-06ea-fda0-bca6-b91ad91264a8
上面这条日志就是切换房间,(输出很简陋(“▔□▔)/),71ee20ff-06ea-fda0-bca6-b91ad91264a8
是房间ID,用Guid模块生成的。
{ type: 1, content: ‘asdasd’ } ‘ef4d090a-e022-9d18-4df9-c2364ca7cf30’
上面这条日志就是切换房间后发送消息,切换到ID为ef4d090a-e022-9d18-4df9-c2364ca7cf30
的房间了。
2. 确定发生问题的模块
Server端看来是暂时没什么问题,看看客户端。
客户端我用了Vue配合Vue-router来开发的,能省了我不少事。
我是以功能来划分模块和页面的,其实说起来就3个:注册登陆、选择房间、进入聊天室。
前面两个模块出问题的几率比较小。所以我重新梳理了一遍最后一个模块。
socket.on('chat message', function (data) {
/*{
msg:{
type:1,
content:"123"
},
userInfo:{
id:123,
nickName:"123",
headimgurl:"123123"
}
}*/
self.addMessage(data);
});
核心代码其实很简单哈,就是监听Server端的chat message消息,然后将消息数据交给addMessage函数处理,实现添加消息记录,自动滚动到底部等等。
我先在addMessage函数中log一下,发现,居然是正常的,我内部维护的一个msgList数组确实是有增加,但是为什么不显示在界面上呢?!,真是纳闷。
3. 寻找问题所在
难道是Vue-router的Bug?难道是Vue的Bug?仔细想想觉得可能性不大,于是测试了一下。自己模拟聊天数据。
在模块载入的ready
钩子中,我用MockJS帮我生成随机的聊天数据,插入msgList
var msglist = Mock.mock({
'list|3-6': [{
msg: {
type: 1,
content: '@sentence(1,2)'
},
userInfo: {
id: 123,
nickName: "@cname",
headimgurl: "123123"
}
}]
});
console.log();
this.msgList = msglist.list;
测试发现一点问题也没有,显示正常。
于是,我想,那我在chat message事件响应的时候将聊天数据追加在数组尾部呢?
结果,我发现,原来此msgList 和彼msgList 不是同一个变量!我切换房间后,发送了两条消息,然后我收到了两条,插入msgList 后,发现输出的msgList的长度就是2,没有包括MockJS帮我生成的数据。
我突然想到,应该是闭包搞的鬼。
最后,经过一点点的调试。最后发现,当切到其他房间时,socket没有重新绑定新的房间,在socket监听事件中,引用着之前的房间的实例,导致垃圾回收机制不能回收变量。所以会出现两个msgList变量。。。。
0x03 总结
要写好单元测试!!!
要写好单元测试!!!
要写好单元测试!!!
重要的事情说三遍。