📜  Javascript 中的服务工作者

📅  最后修改于: 2022-05-13 01:56:31.909000             🧑  作者: Mango

Javascript 中的服务工作者

什么是服务工作者:
Service Worker 是在浏览器后台独立运行的脚本。在用户端,它可以拦截其网络请求并决定加载什么(获取)。
Service Worker 主要提供后台同步、推送通知等功能,它们通常用于“离线优先”应用程序,让开发人员有机会完全控制用户体验。

在此之前,已经有一个名为AppCache的 API,它一直在尝试提供离线体验功能。但是, AppCache API的接口出现了很多问题,Service Worker 在这里,正在解决它们。

Service Worker 生命周期:
Service Worker 的生命周期与网页完全分离。它是一个可编程的网络代理,它在不使用时终止,并在下次需要时重新启动。 Service Worker 严重依赖 Javascript Promises 的使用,因此如果您不熟悉它们,最好复习一下它们。

在安装过程中,Service Worker 可以缓存一些静态资产,例如网页。如果浏览器缓存文件成功,就会安装 service worker。

之后,需要激活worker。在激活期间,服务工作者可以管理和决定对旧缓存发生什么,通常它们会被删除并替换为新版本。

最后,激活后,Service Worker 将控制其范围内的所有页面,而最初注册 Service Worker 的页面则需要刷新。服务工作者在内存使用方面很聪明,如果没有可取的东西并且没有消息事件发生,它将被终止。

下面是浏览器和网络之间的服务工作者位置的图片。

服务人员请求说明

使用 Service Worker 的网站请求链。

先决条件:

  1. HTTPS 除非在本地主机上
    • Service Worker 需要使用 HTTPS 连接。在部署之前,worker 确实在 localhost 服务器下工作,但如果要将其上传到 Internet,则需要在服务器上设置 HTTPS。托管免费演示的一个好地方是GitHub Pages ,它是基于 HTTPS 的服务器。
  2. 浏览器支持
    • Service Worker 在 Internet 上受到ChromeFirefoxOperaSafariEdge的高度支持,这使得它们值得部署。

登记:
要设置服务工作者,它需要注册。这是在您页面的 Javascript 中完成的。一旦注册了服务工作者,这将导致浏览器开始在后台安装它。

// Ensure that the browser supports the service worker API
if (navigator.serviceWorker) {
  // Start registration process on every page load
  window.addEventListener('load', () => {
      navigator.serviceWorker
          // The register function takes as argument
          // the file path to the worker's file
          .register('/service_worker.js')
          // Gives us registration object
          .then(reg => console.log('Service Worker Registered'))
          .catch(swErr => console.log(
                `Service Worker Installation Error: ${swErr}}`));
    });
}

安装:
服务工作者注册后,需要安装它,这是在服务工作者文件中完成的,您通常希望在其中获取缓存资产。

需要采取以下步骤:

  1. 打开缓存
  2. 缓存资产
  3. 确认缓存是否成功
var cacheName = 'geeks-cache-v1';
var cacheAssets = [
    '/assets/pages/offline-page.html',
    '/assets/styles/offline-page.css',
    '/assets/script/offline-page.js',
  
];
  
// Call install Event
self.addEventListener('install', e => {
    // Wait until promise is finished 
    e.waitUntil(
        caches.open(cacheName)
        .then(cache => {
            console.log(`Service Worker: Caching Files: ${cache}`);
            cache.addAll(cacheAssets)
                // When everything is set
                .then(() => self.skipWaiting())
        })
    );
})

激活:

// Call Activate Event
self.addEventListener('activate', e => {
    console.log('Service Worker: Activated');
    // Clean up old caches by looping through all of the
    // caches and deleting any old caches or caches that
    // are not defined in the list
    e.waitUntil(
        caches.keys().then(cacheNames => {
            return Promise.all(
                cacheNames.map(
                    cache => {
                        if (cache !== cacheName) {
                            console.log('Service Worker: Clearing Old Cache');
                            return caches.delete(cache);
                        }
                    }
                )
            )
        })
    );
})

抓取事件:
一旦设置了服务工作者,它应该开始交互并使用缓存的响应。当特定用户浏览网页时,Service Worker 开始接收fetch事件。下面的例子演示了当worker接收到一个fetch事件并搜索匹配的缓存时,如果有,则返回缓存的文件/值,否则返回调用fetch的默认响应

var cacheName = 'geeks-cache-v1';
  
// Call Fetch Event 
self.addEventListener('fetch', e => {
    console.log('Service Worker: Fetching');
    e.respondWith(
        fetch(e.request)
        .then(res => {
            // The response is a stream and in order the browser 
            // to consume the response and in the same time the 
            // cache consuming the response it needs to be 
            // cloned in order to have two streams.
            const resClone = res.clone();
            // Open cache
            caches.open(cacheName)
                .then(cache => {
                    // Add response to cache
                    cache.put(e.request, resClone);
                });
            return res;
        }).catch(
            err => caches.match(e.request)
            .then(res => res)
        )
    );
});

Service Worker 不能: '

  • 访问父对象
  • 访问窗口对象
  • 访问文档对象
  • 访问 DOM

    但是,Service Worker 可以:

  • 缓存资产和 API 调用
  • 管理推送通知
  • 控制网络流量
  • 存储应用程序缓存

    常见用例:

  • 离线优化体验
  • 发送推送通知
  • 后台同步

    参考: https://developers.google.com/web/fundamentals/primers/service-workers/