Chrome扩展后台页面和内容脚本同步

5
假设我有以下代码在Chrome扩展的后台页中。
var opts;
chrome.storage.local.get(options, function(result) {
    opts = result[options];
});

chrome.runtime.onMessage.addListener(function(request, sender, response) {
    if (request.message === 'getOpts')
        response(opts);
});

在我的内容脚本中,我通过消息传递访问opts
chrome.runtime.sendMessage({'message': 'getOpts'}, function(response) {
    console.log(opts);
});

有没有保证在内容脚本运行之前会定义opts?例如,在启动浏览器时,背景页面将运行,并且回调chrome.storage.local.get将被添加到背景页面的消息队列中。Chrome是否会在注入内容脚本之前完成处理该队列?
我可以从内容脚本中调用chrome.storage.local.get,但我的问题更通用,因为我在我的背景页面中还有其他异步处理。目前,我的内容脚本与背景页面检查以确保一切准备就绪(使用间隔进行检查),但我不确定是否需要进行此类检查。

展示一下你的消息传递吧,否则很难回答。 - Xan
嗨Xan,我添加了代码显示消息传递。 - dannyadam
似乎没有任何保证。即使Chrome在加载内容脚本之前处理了后台脚本队列中的所有消息,但是在后台脚本运行完成的时候,chrome.storage.local.get的回调可能还没有在队列上。 - dannyadam
2个回答

1

您实际上可以异步回复消息。

chrome.runtime.onMessage.addListener(function(request, sender, response) {
  if (request.message === 'getOpts') {
    chrome.storage.local.get('options', function(result) {
      response(result[options]);
    });
    return true; // Indicate that response() will be called asynchronously
  }
});

在使用chrome.storage时,这确实很愚蠢,因为该API专门设计用于解决在内容脚本中使用localStorage+消息传递的迂回性质问题;您可以直接从内容脚本查询。但是,在异步处理的一般情况下,您可以推迟回复消息。您只需要从侦听器返回一个true值,表示您还没有完成。

嗨Xan,谢谢你的回复。我也可以直接从我的内容脚本中调用chrome.storage.local.get。然而,我的问题更加通用。我想知道在注入内容脚本之前,是否保证opts已经被定义。 - dannyadam
内容脚本不会在扩展加载时注入。您必须在扩展加载后实际导航才能拥有内容脚本。因此,通常有很大的时间间隔。 - Xan
我在我的帖子中特别使用浏览器启动示例来解决这个问题(因为在浏览器启动时,后台页面和内容脚本都会加载)。 - dannyadam
我曾经进行过一些测试,将后台页面和内容脚本中的时间记录在控制台中。据我回忆,内容脚本是在后台页面完成加载之后注入的,因此addListener调用应该已经运行了。我认为,在我给出的示例类型中,情况变得不太清晰,因为后台页面中的回调必须运行(我想这种情况没有保证,所以我会保留我的代码来检查一切是否准备就绪)。 - dannyadam
让我们在聊天中继续这个讨论。点击此处进入聊天室 - Xan
显示剩余2条评论

0

即使在测试中,也不要依赖于您的变量已定义。通常情况下,由于正常的时间安排,当它接收到消息时,您的变量应该被设置,但是为了确保您应该在后台 onMessage 中检查。我通过在全局中记住是否已经初始化扩展来处理这个问题,并在需要时从 onMessage 中进行初始化。xan 的答案展示了如何在异步初始化完成后使用“return true”来处理消息。

我的 Chrome 扩展 上可以看到一个例子(搜索 bCalled

在那里,您可以看到我有一个 sendResponse 方法,它负责检测回调是否已经被调用,如果没有,则返回 true(假设异步操作正在进行中,并且稍后将调用回调)

您还可以通过在加载该变量的后台代码中模拟延迟来进行实验和测试。


嗨Zig,感谢回复。我已经有了检查一切是否准备就绪并相应进行的代码。我很好奇是否需要这样的代码,我理解你的帖子是在建议必须进行检查。 - dannyadam
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Zig Mandel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接