service worker

目录

提出场景

解决办法

service worker的作用

注册

安装

激活

使用

制定缓存策略

拦截请求与响应

与项目进行通信


提出场景

 一个网页有三个tab页,普通人登录只能访问tab. A,管理人员登录可以访问A,B,而超级管理员可以访问A,B,C。
现在要求做一个提示功能,即所有人如果未登录,会提示未登录;普通人登录并访问B或C,会提示无权限访问B接口、C接口;管理人员登录并访问C,会提示无权限访问C接口;

解决办法

理论上,前端发起fetch请求,根据后端的报错信息可以进行提示,但是因为该项目已经开发完毕;并且包含很多个fetch请求,逐个更改很麻烦,所以使用service worker,把所有的请求与响应全部拦截,然后将根据响应的状态码,提示报错信息。

service worker的作用

一个:可以处理浏览器缓存
二个:可以拦截请求与响应

service worker的基础是web worker,属于多线程,是项目之外的其他线程,所以需要在项目中注册,安装,激活,使用。

注册

//register.js
const start = () => {
  if ('serviceWorker' in navigator) {
    window.addEventListener('load', function() {
      navigator.serviceWorker.register('/serviceWorker.js', {scope: '/'})  
          .then(function(registration) {
            console.log('ServiceWorker registration successful成功 with scope: ', registration.scope);
          })
          .catch(function(err) {
            console.log('ServiceWorker registration failed失败: ', err);
          });
    });
  }
};

⚠️   :在项目中注册serviceWorker.js,注册者(register.js文件)引入被注册者(serviceWorker.js文件) ,路径不是相对路径,而是以项目的根目录为基础。

比如一个react项目的根目录是public文件夹,那么

navigator.serviceWorker.register('/serviceWorker.js', {scope: '/'})

这句话就表示 serviceWorker.js在项目中的位置是:public/serviceWorker.js;
scope: '/':表示的是service Worker监听所有public文件夹下的请求、响应与缓存。
规定,scope只能设置为serviceWorker.js所在文件夹或者子目录。比如你的项目结构:
public
---son1
------grandson
---son2
---son3
---serviceWorker.js
src

那么scope只能设置为:
'/',‘/son1',‘/son2',‘/son3',‘/son1/grandson'
而不能设置为:
'../src'

安装

//serviceWorker.js
self.addEventListener('install', function(event) {
  self.skipWaiting();
});

激活

//serviceWorker.js
self.addEventListener('activate', function(event) {
  self.clients.claim();
});

 网页第一次注册安装service worker的时候,发起的fetch请求不能被service worker拦截,只有第二次起可以,为了解决这个问题,使用了:self.clients.claim();

使用

service worker的两个主要作用,一个是制定浏览器的缓存策略,一个是拦截请求与响应

制定缓存策略

在安装阶段,可以将第一次发起的请求数据(js,html,png等)缓存到本地
在激活阶段可以清除缓存

//安装阶段缓存内容
const CacheName = 'devbup1.1';
const CacheUrls = [
  '/index.html',
  ’/index.js'
];
self.addEventListener('install', function(event) {
  event.waitUntil(
      caches.open(CacheName).then(function(cache) {
        return cache.addAll(CacheUrls);
      }),
  );
});
//在激活阶段清除本地缓存
self.addEventListener('activate', function(event) {
  event.waitUntil(
      Promise.all([
        this.clients.claim(),
        caches.keys().then(function(cachelist) {
          return Promise.all(
              cachelist.map(function(cacheName) {
                if (cacheName !== 'devbup1.1') {
                  return caches.delete(cacheName);
                }
              }),
          );
        }),
      ]),
  );
});

拦截请求与响应

self.addEventListener('fetch', function(event) {
  event.respondWith(
      fetch(event.request).then((response)=>{
        console.log(response.status);
        return response;
      }) 
  );
});

与项目进行通信

以上我们拦截了请求并能够返回一个响应,但是我们判断出响应的状态码,并不能使用alert进行信息提示(因为service worker是基于web worker无法操作dom),所以需要使用web worker的postmessage进行通信

//serviceWorker.js
self.addEventListener('fetch', function(event) {
  event.respondWith(
      fetch(event.request).then((response)=>{
        const {status} = response;
          self.clients.matchAll().then(function(clients) {
            clients.forEach(function(client) { 
              client.postMessage(status);
            });
          });
        return response;
      }) 
  );
});

在注册文件中监听

if ('serviceWorker' in navigator && navigator.serviceWorker) {
  navigator.serviceWorker.addEventListener('message', function(event) {
   alert(event.data);
  });
}

友情链接:好文章

5.1 资源请求的拦截代理 · PWA 应用实战

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值