项目中遇到的JS闭包问题

来源:互联网 发布:linux系统查看ip地址 编辑:程序博客网 时间:2024/06/06 07:02

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 总结

要写好单元测试!!!
要写好单元测试!!!
要写好单元测试!!!
重要的事情说三遍。

0 0