使用后台脚本管理事件

扩展程序是基于事件的程序,用于修改或增强 Chrome 浏览体验。事件是浏览器触发器,例如导航到新网页、移除书签或关闭标签页。扩展程序会在后台脚本中监控这些事件,然后根据指定指令做出响应。

后台网页在需要时加载,在闲置时卸载。以下是一些事件示例:

  • 该扩展程序首次安装或更新到新版本时。
  • 后台网页正在监听事件,并且分派了该事件。
  • 内容脚本或其他扩展程序用于发送消息
  • 扩展程序中的另一个视图(例如弹出式窗口)会调用 runtime.getBackgroundPage

加载完成后,只要后台网页正在执行操作(例如调用 Chrome API 或发出网络请求),它就会保持运行状态。此外,除非关闭所有可见视图和所有消息端口,否则后台页面不会卸载。请注意,打开视图不会导致事件页面加载,而只会阻止该页面在加载完成后关闭。

有效的后台脚本会保持休眠状态,直到它们监听火灾事件,使用指定指令作出响应,然后卸载。

注册后台脚本

后台脚本在清单"background" 字段下注册。它们会列在 "scripts" 键后面的数组中,且 "persistent" 应指定为 false。

{
  "name": "Awesome Test Extension",
  ...
  "background": {
    "scripts": ["background.js"],
    "persistent": false
  },
  ...
}

您可以为模块化代码注册多个后台脚本。

{
    "name": "Awesome Test Extension",
    ...
    "background": {
      "scripts": [
        "backgroundContextMenus.js",
        "backgroundOmniBox.js",
        "backgroundOauth.js"
      ],
      "persistent": false
    },
    ...
  }

如果扩展程序当前使用的是持久性后台页面,请参阅后台迁移指南,了解如何切换到非持久性模型。

初始化该扩展程序

监听 runtime.onInstalled 事件,以在安装扩展程序时初始化扩展程序。使用此事件来设置状态或一次性初始化,例如上下文菜单

chrome.runtime.onInstalled.addListener(function() {
  chrome.contextMenus.create({
    "id": "sampleContextMenu",
    "title": "Sample Context Menu",
    "contexts": ["selection"]
  });
});

设置监听器

围绕扩展程序所依赖的事件设计后台脚本的结构。定义功能相关的事件可以让后台脚本休眠,直到这些事件被触发,并防止扩展程序错过重要的触发器。

监听器必须从网页开头开始同步注册。

chrome.runtime.onInstalled.addListener(function() {
  chrome.contextMenus.create({
    "id": "sampleContextMenu",
    "title": "Sample Context Menu",
    "contexts": ["selection"]
  });
});

// This will run when a bookmark is created.
chrome.bookmarks.onCreated.addListener(function() {
  // do something
});

请勿异步注册监听器,因为系统不会正确触发监听器。

chrome.runtime.onInstalled.addListener(function() {
  // ERROR! Events must be registered synchronously from the start of
  // the page.
  chrome.bookmarks.onCreated.addListener(function() {
    // do something
  });
});

扩展程序可以通过调用 removeListener 从后台脚本中移除监听器。如果移除了某个事件的所有监听器,Chrome 将不再针对该事件加载扩展程序的后台脚本。

chrome.runtime.onMessage.addListener(function(message, sender, reply) {
    chrome.runtime.onMessage.removeListener(event);
});

过滤事件

使用支持事件过滤器的 API 将监听器限制为扩展程序关注的情况。如果扩展程序正在监听 tabs.onUpdated 事件,请尝试改用带有过滤条件的 webNavigation.onCompleted 事件,因为 Tab 键 API 不支持过滤条件。

chrome.webNavigation.onCompleted.addListener(function() {
    alert("This is my favorite website!");
}, {url: [{urlMatches : 'https://www.google.com/'}]});

响应监听器

监听器的作用是在事件触发时触发功能。如需对事件做出响应,请在监听器事件中构建所需的回应结构。

chrome.runtime.onMessage.addListener(function(message, callback) {
  if (message.data == "setAlarm") {
    chrome.alarms.create({delayInMinutes: 5})
  } else if (message.data == "runLogic") {
    chrome.tabs.executeScript({file: 'logic.js'});
  } else if (message.data == "changeColor") {
    chrome.tabs.executeScript(
        {code: 'document.body.style.backgroundColor="orange"'});
  };
});

卸载后台脚本

您应定期保留数据,以便在未收到 onSuspend 的情况下扩展程序崩溃时不会丢失重要信息。可以使用 storage API 来协助完成。

chrome.storage.local.set({variable: variableInformation});

如果扩展程序使用消息传递方式,请确保所有端口都已关闭。在所有消息端口关闭之前,后台脚本不会卸载。通过监听 runtime.Port.onDisconnect 事件,可深入了解打开的端口何时关闭。使用 runtime.Port.disconnect 手动关闭它们。

chrome.runtime.onMessage.addListener(function(message, callback) {
  if (message == 'hello') {
    sendResponse({greeting: 'welcome!'})
  } else if (message == 'goodbye') {
    chrome.runtime.Port.disconnect();
  }
});

通过监控扩展程序条目在 Chrome 的任务管理器中何时出现和消失,可以观察后台脚本的生命周期。

ALT_TEXT_HERE

点击 Chrome 菜单,将光标悬停在更多工具上,然后选择“任务管理器”,即可打开任务管理器。

后台脚本会在几秒钟不活动后自行卸载。如果需要在最后时刻进行清理,请监听 runtime.onSuspend 事件。

chrome.runtime.onSuspend.addListener(function() {
  console.log("Unloading.");
  chrome.browserAction.setBadgeText({text: ""});
});

不过,应优先考虑持久保留数据,而不是依赖于 runtime.onSuspend。这样做无法实现尽可能多的清理,即使发生崩溃也不会有任何帮助。