使用 Service Worker 管理事件

扩展程序是基于事件的程序,用于修改或增强 Chrome 浏览体验。事件是浏览器触发器,例如导航到新页面、移除书签或关闭选项卡。扩展使用后台服务工作线程中的脚本监控这些事件,然后响应指定的指令。

后台服务工作者在需要时加载,并在空闲时卸载。一些事件示例包括:

  • 扩展程序首先安装或更新到新版本。
  • 后台页面正在侦听一个事件,并且该事件被调度。
  • 内容脚本或其他扩展程序发送消息
  • 扩展中的另一个视图(例如弹出窗口)调用 runtime.getBackgroundPage

加载完成后,只要 Service Worker 正在执行操作(例如调用 Chrome API 或发出网络请求),它就会一直运行。此外,在所有可见视图和所有消息端口都关闭之前,Service Worker 不会卸载。

打开视图不会导致 service worker 加载,但只会阻止它在加载后关闭。

有效的后台脚本会一直处于休眠状态,直到它们监听的事件发生,对指定的指令做出反应,然后卸载。

# 注册后台脚本(Register background scripts)

扩展在“background”字段下的清单中注册其后台服务工作者。此字段使用“service_worker”键,该键指定单个 JavaScript 文件。

{
  "name": "Awesome Test Extension",
  ...
  "background": {
    "service_worker": "background.js"
  },
  ...
}

用于“service_worker”的脚本必须位于扩展的根目录中。

您可以选择指定一个额外的 "type": "module" 字段以将 service worker 作为 ES 模块包含在内,这允许您导入更多代码。有关更多信息,请参阅 Service Worker 中的 ES 模块。例如:

"background": {
    "service_worker": "background.js",
    "type": "module"
  }

# 初始化扩展(Initialize the extension)

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

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

# 设置监听器(Set up listeners)

围绕扩展所依赖的事件构建后台脚本。定义功能相关的事件允许后台脚本处于休眠状态,直到这些事件被触发并防止扩展丢失重要的触发器。

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

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

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

不要异步注册侦听器,因为它们不会被正确触发。

chrome.runtime.onInstalled.addListener(() => {
  // 错误!事件必须从开始同步注册
  // the page.
  chrome.bookmarks.onCreated.addListener(() => {
    // do something
  });
});

扩展可以通过调用 removeListener 从其后台脚本中删除侦听器。如果某个事件的所有侦听器都被删除,Chrome 将不再为该事件加载扩展程序的后台脚本。

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

# Filter events(过滤事件)

使用支持事件过滤器(event filters)的 API 将侦听器限制为扩展所关心的情况。如果扩展程序正在侦听 tabs.onUpdated 事件,请尝试使用带有过滤器的 webNavigation.onCompleted 事件,因为 tabs API 不支持过滤器。

const filter = {
  url: [
    {
      urlMatches: 'https://www.google.com/',
    },
  ],
};
chrome.webNavigation.onCompleted.addListener(() => {
  console.info("The user has loaded my favorite website!");
}, filter);

# 对听众作出反应(React to listeners)

一旦事件被触发,监听器就会触发功能。要对事件做出反应,请在侦听器事件内部构建所需的反应。

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

# Unload background scripts(卸载后台脚本)

数据应该定期保存,这样如果扩展程序崩溃而没有收到 onSuspend,重要信息就不会丢失。使用存储(storage) API 来帮助解决这个问题。

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

如果扩展程序使用消息传递(message passing),请确保关闭所有端口。在所有消息端口都关闭之前,后台脚本不会卸载。侦听 runtime.Port.onDisconnect 事件将深入了解开放端口何时关闭。使用 runtime.Port.disconnect 手动关闭它们。

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

后台服务工作者的生命周期可以通过监视扩展条目何时出现和从 Chrome 的任务管理器中消失来观察。

37

通过单击 Chrome 菜单打开任务管理器,将鼠标悬停在更多工具上并选择“任务管理器”。

Service Worker 在几秒钟不活动后自行卸载。如果需要任何最后一分钟的清理,请收听 runtime.onSuspend 事件。

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

但是,与依赖 runtime.onSuspend 相比,在存储(storage) API 中持久化数据应该是首选。它不允许进行尽可能多的清理,并且在发生崩溃时也无济于事。

By.一粒技术服务.

results matching ""

    No results matching ""