运行 只通知脚本一次,即使脚本在多个选项卡上运行

Run notification script only once, even though script runs on multiple tabs

我在 Tampermonkey 脚本中使用了以下代码。

function scriptMain () {
    setTimeout(function(){
        GM_notification ( {
            title: 'Refresh Business Manager', text: 'Your about to be logged out of staging, click here to refresh your login.', image: 'https://i.stack.imgur.com/geLPT.png',
            onclick: () => {
                console.log ("My notice was clicked.");
                location.reload();
            }
        } );
    }, 5*1000);
    console.log ("Script main code ran.");
}

只要浏览器选项卡打开超过 5 秒,代码就会显示一条通知,其中包括一个用于刷新当前浏览器选项卡的按钮。我想使用此脚本每 20 分钟左右提醒我一次浏览器中的登录即将自动注销。

该功能按预期工作,但如果我从我登录的站点打开了 5 个选项卡,我将在页面即将 运行 退出时收到 5 个通知。我希望能够从 Tampermonkey 脚本中判断此脚本是否已经 运行 在另一个选项卡上,不执行或可能只显示一次通知。

我一直在研究 Tampermonkey 文档以获得以下资助:

GM_getTab(callback)
GM_saveTab(tab)
GM_getTabs(callback)

但我似乎无法确定此功能是否可行。

有人可以帮我阐明这个话题,或者分享解决方案吗?

在符合规范的现代浏览器上,您可以在用户脚本中使用 BroadcastChannel 与同一域中的其他选项卡进行通信。使超时稍微随机 - 增加或减少几秒钟以允许所有打开的选项卡进行协调。发送通知时,也在 BroadcastChannel 中发送一条消息,告诉用户脚本的其他实例也重置它们的计时器。

const channel = new BroadcastChannel('logout-notify');

let timeoutId;
function makeTimeout() {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(function () {
        GM_notification({
            title: 'Refresh Business Manager', text: 'Your about to be logged out of staging, click here to refresh your login.', image: 'https://i.stack.imgur.com/geLPT.png',
            onclick: () => {
                console.log("My notice was clicked.");
                location.reload();
            }
        });
        channel.postMessage('notified');
    }, 1000 * 60 * 20 + (Math.random() * 10000)); // 20 minutes plus up to 10 seconds
}

// When below runs, another tab created a notification
// reset the timeout for this tab, schedule another one for 20ish minutes from now
channel.onmessage = makeTimeout;

// initialize timeout on pageload?
makeTimeout();

此代码将导致警报最多每 20 分钟显示一次。如果您关闭您正在处理的一个选项卡,其他选项卡将不间断地占用空闲空间。