如何避免“扩展上下文无效"在扩展更新后发送消息时出错? [英] How to avoid "Extension context invalidated" errors when messaging AFTER an Extension update?

查看:12
本文介绍了如何避免“扩展上下文无效"在扩展更新后发送消息时出错?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在发布更新后为我的 Chrome 扩展程序的用户创造流畅的体验.

I am trying to create a smooth experience for users of my Chrome Extension after I release updates.

我在更新应用程序时重新注入我的内容脚本,即使用户在扩展程序更新后未刷新的页面上继续使用我的扩展程序,我的功能仍然有效.刷新页面是理想的,但我不想强迫我的用户这样做.

I reinject my content script on an update of the app, and my functionality works even if the user continues to use my Extension on a page that has NOT been refreshed after the Extension update. Refreshing the page is ideal, but I don't want to have to force that on my users.

但是,在扩展更新后但在页面刷新之前,当我的代码尝试从内容脚本/页面向我的后台发送消息时,我的内容脚本控制台(内容脚本插入的页面)中出现以下错误页面:

However, I get the following errors in my content script console (the page the content script is inserted into) AFTER the Extension updates but BEFORE the page is refreshed when my code attempts to message from the content script/page to my background page:

未捕获的错误:扩展上下文无效.

Uncaught Error: Extension context invalidated.

有没有办法重建"连接?我已经尝试了一个长期存在的端口和定期消息传递 - 更新扩展具有相同的效果.

Is there a way to 'rebuild' the connection? I've tried a long-lived port and regular messaging - updating the Extension has the same effect.

任何想法/方向表示赞赏.

Any ideas/direction appreciated.

这是我抛出错误的简单消息传递代码(在内容脚本中)...但我能够与后台脚本通信:

Here is my simple messaging code (in the content script) that throws the error...but IS able to communicate with the background script:

chrome.runtime.sendMessage({ msg: "recordFeedback", obj: commentObj, source: source}, function(response){
  console.log('Sent to DB...response was: ', response, response.recordFeedbackResponse);
});

推荐答案

卸载扩展时,现有内容脚本失去与扩展其余部分的连接 - 即端口关闭,它们将无法使用 runtime.sendMessage()——但内容脚本本身仍然继续工作,因为它们已经被注入到它们的页面中.

When an extension is unloaded, the existing content scripts lose their connection to the rest of the extension—i.e. ports close, and they would be unable to use runtime.sendMessage()—but the content scripts themselves still continue to work, as they're already injected into their pages.

重新加载扩展时也是一样:那些现有的内容脚本仍然存在,但无法发送消息;尝试这样做会导致您遇到的错误.此外,由于扩展程序在加载时将它们的内容脚本注入现有选项卡是很常见的(在 Chrome 上 - Firefox 会自动执行此操作),您最终将在给定选项卡中运行多个内容脚本副本:原来的,现在断开的一个,和当前的,连接的一个.

It's the same when an extension is reloaded: those existing content scripts will still be there, but unable to send messages; attempts to do so cause errors like the one you're encountering. Further, as it's common for extensions to inject their content scripts into existing tabs when they are loaded (on Chrome—Firefox does that automatically), you'll end up with more than one copy of the content script running in a given tab: the original, now-disconnected one, and the current, connected one.

在以下情况下可能会出现问题:(1) 您的原始内容脚本仍在尝试与扩展程序的其余部分进行通信,或者 (2) 您的原始内容脚本执行诸如修改 DOM 之类的操作,因为您最终可能会进行这些更改做过不止一次.

Problems can arise if either: (1) your original content script is still trying to communicate with the rest of the extension or (2) your original content script does things like modify the DOM, as you could end up with those changes done more than once.

这可能就是为什么即使在重新注入内容脚本后仍然出现错误的原因:错误来自仍然存在但已断开连接的原始内容脚本.

这解释了我之前研究这个问题时发现的一些有用的背景信息.请注意,Firefox 会自动卸载内容脚本(稍后会详细介绍).

This has paraphrased some helpful background information that I found when previously researching this problem. Note that Firefox automatically unloads content scripts (more on that later).

如果您没有自动重新注入内容脚本,那么您可以尝试让现有脚本在升级时重新连接,根据 wOxxOm 上面的评论.

If you are not automatically re-injecting your content scripts, then you can try to get the existing script to reconnect on upgrade, as per wOxxOm's comment above.

这里有一些进一步的信息和建议,如果您注入新的内容脚本并希望 禁用原始的、断开连接的、当注入新的.

Here's some further info and advice, particularly useful if you inject new content scripts and want to disable the original, disconnected, one when a new one is injected.

无论您是想尝试使用现有内容脚本重新连接,还是停止原始内容脚本进行进一步更改并注入新内容,您都需要检测是否发生了卸载.您可以使用端口的 disconnect 处理程序来捕获扩展程序何时卸载.如果您的扩展程序只使用简单的一次性消息传递,而不是端口,那么该代码就像在内容脚本启动时运行以下代码一样简单(我第一次在 lydell).

Regardless of whether you would like to try to reconnect using the existing content script, or stop the original content script from making further changes and inject a new one, you need to detect that an unload has occurred. You can use the port's disconnect handler to catch when your extension is unloaded. If your extension only uses simple one-time message passing, and not ports, then that code is as simple as running the following when your content script starts up (I first saw this technique in some code from lydell).

browser.runtime.connect().onDisconnect.addListener(function() {
    // clean up when content script gets disconnected
})

在 Firefox 上,端口的 disconnect 不会被触发,因为内容脚本在收到之前已被删除.这样做的优点是不需要进行这种检测(手动内容脚本注入也不是,因为内容脚本也是自动注入的),但这确实意味着没有机会重置内容脚本对 DOM 所做的任何更改正在运行.

On Firefox, the port's disconnect is not fired, because the content scripts are removed before they would receive it. This has the advantage that this detection isn't necessary (nor is manual content script injection, as content scripts are injected automatically too), but it does mean that there's no opportunity to reset any changes made to the DOM by your content script when it was running.

这篇关于如何避免“扩展上下文无效"在扩展更新后发送消息时出错?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆