Show progress while caching files using a service

2019-05-07 04:56发布

问题:

I'm not too familiar with JavaScript and have a hard time getting into service workers.

I want to make a whole webapp available offline using service workers to cache the necessary files at page load. Though this is working, it takes quite some time until all the files are downloaded to disk, which makes the browser unresponsive and the user impatient.

I wonder, what is the best way to show progress while the service worker is doing its magic? In the way of "Downloading file 25 of 100".

How can the client know the progress of the service worker? Since the worker has no DOM access. Do I have to use messages between the worker and the client?

This is my first question here and I hope I made myself clear, do not post a duplicate (didn't find anything) and obeyed all the rules.

Thanks in advance for any help or guidance.

回答1:

The example below emits progress indicator events from a Service Worker. You can keep a running progress total for multiple PWA requests reworking the code a bit and changing const total (declared here) to let total in global scope to calculate a running byte count total of all the responses. Use HTTP2, otherwise the "total" size will grow as new responses start to come in, yielding inaccurate progress bars. HTTP2 will most likely start all responses at the same time, allowing you to calculate the grand total from the onset, which provides better UX accuracy.

https://fetch-progress.anthum.com/sw-basic/

ReadableStream is required and not fully implemented by browsers. Mind the browser support.



回答2:

I am new to JavaScript as well as PWAs. I had the very much same questions (How I can find out that my contents are available offline means have been loaded into the cache for off-line browsing?), looked around on the web and finally find out that the Service Workers (SW) can’t speak to the clients other than a SW may do a (console.log) after completing the loading using add() and/or addAll() methods. I think the best would be to find out the limit available for the storage and usage using estimate.quota() and estimate.usage(), as you might already know these are the methods of the of the Storage Api.

var storageMax = Math.round(estimate.quota/(1024*1024))

This will give you the maximum storage capacity available in Mib and the following line of code will give you the storage you have consumed.

Var storageValue = Math.round(estimate.usage/(1024*1024))

<progress value=" storageValue " max=" storageMax "></progress>

If you use the above mentioned progress bar onto your [index.html or whichever] page it will at least show you some sort of progress in terms of some contents being loaded and your initial capacity. Now come the second part of it, If in JavaScript (which I am sure we can), we can find out how much our contents are in size e.g. if I can find out the size of the folder(s) which contains videos to be loaded for the offline storage then the we can have another progress bar

Var folderSize = [folder1] + [folder2] + …;
<progress value=" storageValue " max=" folderSize "></progress>

This will give you very much precise progress bar showing folderSize as the maximum length of the progress bar and the storageValue as the contents been loaded into it. I am still trying to find out how do I find the size of a folder in JavaScript, so the answer is practically incomplete but logically complete, I think so



回答3:

At the moment, there is no way of tracking the download progress of your PWA. But what you can do is when the service worker has registered, pop up a message using a toaster or something stating that your PWA is being saved for offline caching. Then pop another message when it is done. Something like the code below

window.addEventListener('load', function () {
    navigator.serviceWorker.register('/service-worker.js')
    .then(function (registration) {
        registration.onupdatefound = function () {
            // toaster('Saving assets for offline caching!');

            const installingWorker = registration.installing;
            installingWorker.onstatechange = function () {
                switch (installingWorker.state) {
                    case 'installed':
                        if (!navigator.serviceWorker.controller) {
                            // toaster('Caching complete!');
                        }
                        break;

                    case 'redundant':
                        throw Error('The installing service worker became redundant.');
                }
            };
        };