clearInterval失效致消息通知异常:后续聊天提示音延迟问题
问题分析与修复方案
核心问题
你的脚本里messageBoxesCounter是在自执行函数的最外层定义的,属于IIFE范围内的全局变量。当关闭聊天触发cleanIntervals清除定时器并重启main时,这个计数器并没有被重置为新聊天窗口的当前消息数,仍然保留着上一次聊天结束时的数值。所以第二次聊天时,只有当新消息数超过这个旧的计数时,才会触发提示音。
修复步骤
重置计数器到当前聊天的消息数
在cleanIntervals函数里,重启main之前,重新获取当前的消息数并赋值给messageBoxesCounter,确保新的监听周期从当前状态开始计数:var cleanIntervals = function() { console.log('Chat Alert: Cleaning up Intervals'); clearInterval(window.newIncomingMessageInterval); // 重置计数器为当前聊天的消息数 messageBoxesCounter = document.querySelectorAll("div[class^='Body'][direction='Incoming']").length; main() }优化关闭按钮的检测逻辑
当前代码在定时器的每一次循环里都会检查关闭按钮,只要按钮存在就会触发cleanIntervals,这会导致频繁重启定时器。可以改成只在按钮出现时执行一次清理,避免重复操作:// 在IIFE内部添加监听逻辑 var closeButtonObserver = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.addedNodes.length) { var closeBtn = $("button[data-testid='ccp-next-contact-button']"); if (closeBtn.length > 0) { console.log('Chat Alert: Close contact button detected, cleaning intervals'); cleanIntervals(); // 检测到后暂时停止观察,避免重复触发 closeButtonObserver.disconnect(); } } }); }); // 监听页面变化,检测关闭按钮的出现 closeButtonObserver.observe(document.body, { childList: true, subtree: true });同时把
main函数里的按钮检测代码删掉,避免冲突。可选:将计数器移到main函数内部
把messageBoxesCounter的定义移到main函数里,每次启动定时器时都初始化当前的消息数,从根源避免旧值残留:function main() { // 初始化当前消息数 var messageBoxesCounter = document.querySelectorAll("div[class^='Body'][direction='Incoming']").length; window.newIncomingMessageInterval = setInterval(function() { var messageBoxes = document.querySelectorAll("div[class^='Body'][direction='Incoming']"); var messageBoxesCounterNew = messageBoxes.length; console.log('Chat Alert: NOTIFY: ' + messageBoxes.length); if (messageBoxesCounter < messageBoxesCounterNew) { console.log('Chat Alert: NEW MESSAGE!'); if (user_settings.notify) { audioElement.play(); } messageBoxesCounter = messageBoxesCounterNew; } else { console.log('Chat Alert: No new message'); } }, 1000); }这种方式下,每次调用
main都会重新初始化计数器,不需要在cleanIntervals里额外处理。
完整修复后的代码示例
// SETTINGS var notify = true; // true or false / to enable audio notifications on incoming messages. // -------------------------------------------------------------------------------------------------------------------- // MAIN SCRIPT var user_settings = { notify: notify } var audioElement = document.createElement('audio'); audioElement.setAttribute('src', 'https://PrivateDirectory/ChatAlert/notification.mp3'); (function($, user_settings) { 'use strict'; console.log(user_settings) console.log('Chat Alert: Cleaner Started'); var closeButtonObserver = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.addedNodes.length) { var closeBtn = $("button[data-testid='ccp-next-contact-button']"); if (closeBtn.length > 0) { console.log('Chat Alert: Close contact button detected, cleaning intervals'); cleanIntervals(); closeButtonObserver.disconnect(); } } }); }); closeButtonObserver.observe(document.body, { childList: true, subtree: true }); var cleanIntervals = function() { console.log('Chat Alert: Cleaning up Intervals'); clearInterval(window.newIncomingMessageInterval); // 重启监听时重新初始化观察器 closeButtonObserver.observe(document.body, { childList: true, subtree: true }); main() } function main() { var messageBoxesCounter = document.querySelectorAll("div[class^='Body'][direction='Incoming']").length; window.newIncomingMessageInterval = setInterval(function() { var messageBoxes = document.querySelectorAll("div[class^='Body'][direction='Incoming']"); var messageBoxesCounterNew = messageBoxes.length; console.log('Chat Alert: NOTIFY: ' + messageBoxes.length); if (messageBoxesCounter < messageBoxesCounterNew) { console.log('Chat Alert: NEW MESSAGE!'); if (user_settings.notify) { audioElement.play(); } messageBoxesCounter = messageBoxesCounterNew; } else { console.log('Chat Alert: No new message'); } }, 1000); } main(); })(window.jQuery, user_settings);
内容的提问来源于stack exchange,提问作者MonkeyScriptingTamperer
相关产品推荐
相关产品推荐

