admin管理员组

文章数量:1434967

I've been asked to create a service worker which will have the ability to intercept requests and redirect them to stored mock data. I have never done something like this before so I am struggling a bit. The service worker is activated when testMode=true is added to the URL. I have 2 files for dealing with. This is what I have so far:

TestMode.ts

class TestMode {
    constructor() {
        if (!this.isEnabled()) {
            return;
        }

        if (!('serviceWorker' in navigator)) {
            console.log('Browser does not support service workers');
            return;
        }

        this.init();
    }

    private init(): void {
        navigator.serviceWorker
            .register('planner-worker/js/worker.min.js')
            .then(this.handleRegistration)
            .catch((error) => { throw new Error('Service Worker registration failed: ' + error.message); });

        navigator.serviceWorker.addEventListener('message', event => {
            // event is a MessageEvent object
            console.log(`The service worker sent me a message: ${event.data}`);
        });

        navigator.serviceWorker.ready.then( registration => {
            if (!registration.active) {
                console.log('failed to municate')

                return;
            }

            registration.active.postMessage("Hi service worker");
        });
    }

    private handleRegistration(registration: ServiceWorkerRegistration): void {
        registration.update();

        console.log('Registration successful, scope is:', registration.scope);
    }

    private isEnabled(): boolean {
        return locationService.hasParam('testMode');
    }
}

export default new TestMode();

serviceWorker.ts

const CACHE_NAME = 'mockData-cache';

const MOCK_DATA: Record<string, string> = {
    '/units/all?availability=Active&roomTypeHandle=kitchens': 'mock-data/unitData.json',
    '/frontal-ranges/kitchens?' : 'mock-data/kitchensData.json',
    '/carcase-ranges/?availability=Active&roomTypeHandle=kitchens' : 'mock-data/carcaseRangesData.json'
};


self.addEventListener('install', event => {
    console.log('Attempting to install service worker and cache static assets');
    event.waitUntil(
        caches.open(CACHE_NAME)
            .then(cache => {
                return cache.addAll(Object.values(MOCK_DATA));
            })
    );
});


self.addEventListener('activate', function(event) {
    console.log('Claiming control');
    return self.clients.claim();
});
self.addEventListener( "fetch", event => {
    console.log('WORKER: Fetching', event.request);
});

What I have so far works, the service worker is registered and that mock data json files are stored in the cache.

What I am not sure what to do is when a certain request is made, the service worker will use the mock data stored in the cache instead.

For example, how can I get it so that when the request is made for: /units/all?availability=Active&roomTypeHandle=kitchens the service worker will redirect to mock-data/unitData.json in the cache instead?

I hope I've made sense, any help would be really appreciated, this is all new to me.

I've been asked to create a service worker which will have the ability to intercept requests and redirect them to stored mock data. I have never done something like this before so I am struggling a bit. The service worker is activated when testMode=true is added to the URL. I have 2 files for dealing with. This is what I have so far:

TestMode.ts

class TestMode {
    constructor() {
        if (!this.isEnabled()) {
            return;
        }

        if (!('serviceWorker' in navigator)) {
            console.log('Browser does not support service workers');
            return;
        }

        this.init();
    }

    private init(): void {
        navigator.serviceWorker
            .register('planner-worker/js/worker.min.js')
            .then(this.handleRegistration)
            .catch((error) => { throw new Error('Service Worker registration failed: ' + error.message); });

        navigator.serviceWorker.addEventListener('message', event => {
            // event is a MessageEvent object
            console.log(`The service worker sent me a message: ${event.data}`);
        });

        navigator.serviceWorker.ready.then( registration => {
            if (!registration.active) {
                console.log('failed to municate')

                return;
            }

            registration.active.postMessage("Hi service worker");
        });
    }

    private handleRegistration(registration: ServiceWorkerRegistration): void {
        registration.update();

        console.log('Registration successful, scope is:', registration.scope);
    }

    private isEnabled(): boolean {
        return locationService.hasParam('testMode');
    }
}

export default new TestMode();

serviceWorker.ts

const CACHE_NAME = 'mockData-cache';

const MOCK_DATA: Record<string, string> = {
    '/units/all?availability=Active&roomTypeHandle=kitchens': 'mock-data/unitData.json',
    '/frontal-ranges/kitchens?' : 'mock-data/kitchensData.json',
    '/carcase-ranges/?availability=Active&roomTypeHandle=kitchens' : 'mock-data/carcaseRangesData.json'
};


self.addEventListener('install', event => {
    console.log('Attempting to install service worker and cache static assets');
    event.waitUntil(
        caches.open(CACHE_NAME)
            .then(cache => {
                return cache.addAll(Object.values(MOCK_DATA));
            })
    );
});


self.addEventListener('activate', function(event) {
    console.log('Claiming control');
    return self.clients.claim();
});
self.addEventListener( "fetch", event => {
    console.log('WORKER: Fetching', event.request);
});

What I have so far works, the service worker is registered and that mock data json files are stored in the cache.

What I am not sure what to do is when a certain request is made, the service worker will use the mock data stored in the cache instead.

For example, how can I get it so that when the request is made for: /units/all?availability=Active&roomTypeHandle=kitchens the service worker will redirect to mock-data/unitData.json in the cache instead?

I hope I've made sense, any help would be really appreciated, this is all new to me.

Share Improve this question asked Apr 30, 2021 at 11:55 lross12lross12 771 silver badge9 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 4

The logic around handling ining requests and generating responses (either from the cache, network, or some bination of the two) needs to be implemented in your fetch event handler.

Here's how I'd structure your fetch handler given your cache contents and use case:

self.addEventListener('fetch', (event) => {
  // Using a URL object will make routing easier.
  const url = new URL(event.request.url);
  const pathAndQuery = url.pathname + url.search;

  if (pathAndQuery in MOCK_DATA) {
    const cacheKey = MOCK_DATA[pathAndQuery];
    event.respondWith(
      caches.match(cacheKey, {
        cacheName: CACHE_NAME,
      })
    );
  }

  // If pathAndQuery isn't in MOCK_DATA, then respondWith()
  // won't be called, and the default network behavior will
  // be used for this request.
});

You might be able to use a library like https://mswjs.io/ as an alternative to writing this by hand, but that's the general idea if you decide to do it yourself.

本文标签: javascriptUsing ServiceWorker to intercept and redirect requestsStack Overflow