service-worker - 事件处理程序之外的 Service Worker 中的代码何时运行?

标签 service-worker

(我正在解释 Rich Harris 在“Stuff I wish I'd known sooner about service workers ”要点中提出的问题。)

如果我的 Service Worker 中有在事件处理程序之外运行的代码,它何时运行?

而且,与此密切相关的是,放入 install 之间有什么区别?处理程序并将其完全放在事件处理程序之外?

最佳答案

一般来说,在任何事件处理程序之外的代码,在服务 worker 全局范围的“顶级”中,每次服务 worker 线程(/进程)启动时都会运行。 Service Worker 线程可以在任意时间启动(和停止),并且它与它控制的网页的生命周期无关。

(频繁启动/停止服务工作线程是一种性能/电池优化,并确保,例如,仅仅因为您浏览到已注册服务工作线程的页面,您不会在后台获得额外的空闲线程旋转。 )

另一方面是每次服务工作线程停止时,任何现有的全局状态都会被破坏。因此,虽然您可以进行某些优化,例如将打开的 IndexedDB 连接存储在全局状态中以希望在多个事件之间共享它,但如果线程在事件处理程序调用之间被终止,您需要准备重新初始化它们。

与这个问题密切相关的是我看到的关于 install 的误解。事件处理程序。我看到一些开发人员使用 install处理程序初始化全局状态,然后它们在其他事件处理程序中依赖,例如 fetch .这是危险的,并且可能会导致生产中的错误。 install handler 每个版本的 Service Worker 触发一次,通常最适用于与 Service Worker 版本控制相关的任务,例如缓存该版本所需的新资源或更新资源。后 install处理程序已成功完成,服务 worker 的给定版本将被视为“已安装”,并且 install当 Service Worker 启动处理时不会再次触发处理程序,例如 fetchmessage事件。

因此,如果在处理之前需要初始化全局状态,例如 fetch事件,您可以在顶级 Service Worker 全局范围内执行此操作(可选择等待在 fetch 事件处理程序中解析的 promise ,以确保任何异步操作已完成)。做 不是 依赖 install设置全局作用域的处理程序!

这是一个说明其中一些要点的示例:

// Assume this code lives in service-worker.js

// This is top-level code, outside of an event handler.
// You can use it to manage global state.

// _db will cache an open IndexedDB connection.
let _db;
const dbPromise = () => {
  if (_db) {
    return Promise.resolve(_db);
  }

  // Assume we're using some Promise-friendly IndexedDB wrapper.
  // E.g., https://www.npmjs.com/package/idb
  return idb.open('my-db', 1, upgradeDB => {
    return upgradeDB.createObjectStore('key-val');
  }).then(db => {
    _db = db;
    return db;
  });
};

self.addEventListener('install', event => {
  // `install` is fired once per version of service-worker.js.
  // Do **not** use it to manage global state!
  // You can use it to, e.g., cache resources using the Cache Storage API.
});

self.addEventListener('fetch', event => {
  event.respondWith(
    // Wait on dbPromise to resolve. If _db is already set, because the
    // service worker hasn't been killed in between event handlers, the promise
    // will resolve right away and the open connection will be reused.
    // Otherwise, if the global state was reset, then a new IndexedDB
    // connection will be opened.
    dbPromise().then(db => {
      // Do something with IndexedDB, and eventually return a `Response`.
    });
  );
});

关于service-worker - 事件处理程序之外的 Service Worker 中的代码何时运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38835273/

相关文章:

angular - 无法使用 Angular cli 以 Angular 注册服务 worker

reactjs - React App 中缺少 serviceWorker

service-worker - 我的 service worker 什么时候更新?

javascript - Service Worker 使 js 运行两次

node.js - 添加到主屏幕不会出现在我的 Angular 应用程序中

javascript - 如何在 ServiceWorker 中处理 Session 过期

facebook - 在 Facebook 浏览器中更新 Service Worker

javascript - 是否可以直接从服务 worker (ServiceWorkerGlobalScope)读取变量?

service-worker - service worker 在第一次加载时获取事件

progressive-web-apps - 如何从我的页面中调用我的 ServiceWorker 上的方法?