Service Worker的使用

Service Worker到底是干什么的?

拦截和处理浏览器和网络发出的请求,且开发者可以缓存网页的资源文件(如HTML、CSS、JavaScript、图像等),使用户在离线情况下仍能够访问应用程序,或者在网络条件较差时提供更快的加载速度。

使用场景

  1. 离线缓存(Offline caching):通过缓存资源文件,使应用程序在断网情况下仍然可用。
  2. 推送通知(Push notifications):使网站能够向用户发送推送通知,即使用户当前没有打开网站。
  3. 后台同步(Background sync):在网络连接恢复后,可以在后台同步数据,而不必依赖用户打开应用程序。
  4. 性能优化(Performance optimization):通过缓存策略和智能加载,提高网页的加载速度和性能。

如何使用

首先我们来直接模拟建立一个正常地请求

建立页面index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>News App</title>
  <link rel="stylesheet" href="./styles.css">
</head>
<body>
<h1>News App</h1>
<div id="news-list">
</div>
<script src="./script.js"></script>
</body>
</html>
模拟数据 news.json
[
  {
    "title": "Breaking News",
    "content": "This is a breaking news article."
  },
  {
    "title": "Latest Update",
    "content": "Here is the latest update on the ongoing event."
  }
]
建立请求并显示数据 script.js
document.addEventListener('DOMContentLoaded', async () => {
  try {
    const response = await fetch('/news.json');
    const newsData = await response.json();

    const newsList = document.getElementById('news-list');
    newsData.forEach(article => {
      const articleElement = document.createElement('div');
      articleElement.innerHTML = `
        <h2>${article.title}</h2>
        <p>${article.content}</p>
      `;
      newsList.appendChild(articleElement);
    });
  } catch (error) {
    console.error('Error fetching news:', error);
  }
});
运行看结果

运行结果
以上都是非常常规的请求数据的方法,那我们再来看看加入service worker之后的

加入service worker

添加service-worker.js
const CACHE_NAME = 'news-app-cache-v1';
const urlsToCache = [
  '/index.html',
  '/script.js',
  '/news.json'
];

// 创建一个缓存
self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(cache => {
        return cache.addAll(urlsToCache);
      })
  );
});

// 拦截请求
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request)
      .then(cachedResponse => {
        // 如果缓存中存在请求的响应,则直接返回缓存的响应
        if (cachedResponse) {
          console.log('Response from cache:', event.request.url);
          return cachedResponse;
        }

        // 如果缓存中不存在请求的响应,则继续向网络发出请求
        return fetch(event.request)
          .then(networkResponse => {
            // 将从网络获取到的响应添加到缓存中
            return caches.open('dynamic-cache')
              .then(cache => {
                cache.put(event.request, networkResponse.clone());
                return networkResponse;
              });
          })
          .catch(error => {
            console.error('Fetch error:', error);
            // 如果网络请求失败,可以返回一个自定义的响应
            return new Response('Network request failed!', {
              status: 500,
              statusText: 'Internal Server Error'
            });
          });
      })
  );
});

修改script.js
document.addEventListener('DOMContentLoaded', async () => {
  try {
    const response = await fetch('/news.json');
    const newsData = await response.json();
    const newsList = document.getElementById('news-list');
    newsData.forEach(article => {
      const articleElement = document.createElement('div');
      articleElement.innerHTML = `
        <h2>${article.title}</h2>
        <p>${article.content}</p>
      `;
      newsList.appendChild(articleElement);
    });
  } catch (error) {
    console.error('Error fetching news:', error);
  }

  // 添加部分 判断是否可用,可用就进行注册
  if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('./service-worker.js')
      .then(registration => {
        console.log('Service Worker registered:', registration);
      })
      .catch(error => {
        console.error('Service Worker registration failed:', error);
      });
  }
});
来看看成果

首先第一次请求时,我们看到还是实打实地去进行请求
第一次请求
我们来刷新一下页面,就会瞬间发现,请求都改成了从缓存中获取,大大节省了我们的请求时间
刷新页面后

添加清理缓存

假如我们要清理掉缓存,也是非常简单,调用caches.delete即可
修改index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>News App</title>
</head>
<body>
<h1>News App</h1>
<div id="news-list">
</div>

<script src="./script.js"></script>
<script>
  function handleClick() {
    caches.keys().then(cacheNames => {
      return Promise.all(
        cacheNames.map(cacheName => {
          return caches.delete(cacheName);
        })
      );
    }).then(() => {
      console.log('All caches have been deleted');
      // 在页面中显示消息,通知用户缓存已被清除
      alert('缓存已清除');
    }).catch(error => {
      console.error('Cache deletion failed:', error);
      // 如果删除缓存失败,也可以在页面中显示错误消息
      alert('清除缓存失败');
    });
  }
</script>
</body>
</html>

总结

以上就是基于Service Worker做的缓存文件功能,当然因为其本身拦截和处理浏览器和网络发出请求的特性,可以做到的东西其实还有挺多的,比如在基于self.addEventListener('fetch', event => {更改请求头,更改返回主体,等等功能
比如

self.addEventListener('fetch', event => {
  event.respondWith(
    // 返回自定义的响应
    new Response('Hello from Service Worker!', {
      headers: { 'Content-Type': 'text/plain' }
    })
  );
});
  • 16
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值