Firebase搭配JavaScript切换接收方时消息重复拉取问题如何解决
问题场景
使用Firebase与JavaScript开发聊天应用时,多次切换消息接收方会触发异常:消息仅向数据库成功发送1次,前端却会多次拉取到同一条消息,造成重复渲染。
实际运行表现:最初收发的3条消息展示正常,执行切换接收方操作后,拉取到的已发送消息会出现重复展示,异常效果如下:
复现代码
var select = document.getElementById("odbiorcy"); select.addEventListener("change", function handleChange(event) { receiver = select.options[select.selectedIndex].text; console.log("gonna fetch"); document.getElementById("messages").innerHTML = ""; fetchChat = db.ref("messages/" + username + "/" + receiver + "/"); fetchChat.on("child_added", function (snapshot) { const messages = snapshot.val(); const msg = "<li>" + messages.usr + " : " + messages.msg + "</li>"; document.getElementById("messages").innerHTML += msg; }); });
故障原因
每次下拉选择框触发change事件时,代码都会为对应路径的数据库引用新增一个child_added事件监听,但从未解绑之前绑定的旧监听。切换多少次接收方,就会累计多少个存活的监听器:当拉取消息时,所有未被销毁的监听器都会触发回调执行渲染逻辑,同一条消息自然会被重复插入页面多次。
修复方案
每次绑定新的消息监听前,先调用off()方法解绑当前引用上挂载的旧child_added监听,避免监听器累计残留。修复后代码如下:
var select = document.getElementById("odbiorcy"); let fetchChat = null; select.addEventListener("change", function handleChange(event) { receiver = select.options[select.selectedIndex].text; console.log("gonna fetch"); document.getElementById("messages").innerHTML = ""; // 解绑上一个聊天路径的监听 if (fetchChat) { fetchChat.off("child_added"); } fetchChat = db.ref("messages/" + username + "/" + receiver + "/"); fetchChat.on("child_added", function (snapshot) { const messages = snapshot.val(); const msg = "<li>" + messages.usr + " : " + messages.msg + "</li>"; document.getElementById("messages").innerHTML += msg; }); });
补充提示:如果使用Firebase 9+的Modular SDK版本,解绑监听需要调用
onChildAdded返回的取消订阅函数,逻辑本质和上述方案一致,都是在不需要监听时主动销毁监听器。
内容的提问来源于stack exchange,提问作者smardzi420
相关产品推荐
相关产品推荐

