我们的 Chrome 扩展程序具有相互通信的内容和后台脚本。更新插件后,后台脚本将停止,内容脚本开始收到错误:扩展上下文无效。
。在 V2 中,我们使用 port.onDisconnect
事件,如所述 here清理东西。但在 V3 中,该事件也会在 5 分钟后发送(此时后台 Service Worker 自动终止)。所以这个事件现在意味着要么扩展卸载(并且应该完成清理),要么只是软件生命周期事件(不需要清理,重新连接就可以)。
所以问题是,如何明确确定是否需要清理。
我已经尝试过:
chrome.management.
事件:onDisabled
等。但不幸的是,chrome.management
在我的内容脚本中未定义。- 检查
port.onDisconnected
回调中的chrome.runtime.id
以确定插件是否已卸载。但此时该 ID 仍然存在。 - 再次在
port.onDisconnected
内,尝试再次执行chrome.runtime.connect()
并捕获异常。但无一异常(exception)!端口创建成功,但它既没有收到消息,也没有收到自己的onDisconnected
事件。 - 在
setTimeout(..., 0)
和setTimeout(..., 100)
中尝试第 3 点。前者也不产生异常。后者确实如此,但它引入了一个值得怀疑的持续时间延迟(为什么是 100?它会在 CPU 过载的情况下工作吗?)以及当其他插件功能可能尝试发送具有不可预测结果的消息时潜在的竞争条件。因此,我希望有一个更可靠的解决方案。
最佳答案
感谢wOxxOm's suggestions ,我找到了一个目前似乎有效的解决方案:每隔一段时间(<5 秒)断开内容脚本中的端口,然后再次重新连接。代码如下所示:
let portToBackground: chrome.runtime.Port | undefined = openPortToBackground();
function openPortToBackground(): chrome.runtime.Port {
const port = chrome.runtime.connect();
const timeout = setTimeout(() => {
console.log('reconnecting');
portToBackground = openPortToBackground();
port.disconnect();
}, 2 * 60 * 1000); // 2 minutes here, just to be sure
port.onDisconnect.addListener(() => {
clearTimeout(timeout);
if (port !== portToBackground) return;
// perform the cleanup
});
return port;
}
export function isExtensionContextInvalidated(): boolean {
return !portToBackground;
}
关于google-chrome-extension - 如何检测带有 Manifest v3 的 Chrome 扩展程序是否已卸载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72229032/