Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle dependencies in Service Worker?

I have Service Worker that load file from BrowserFS if the path contain __browserfs__, simplified code like this:

function loadDependecies() {
    self.skipWaiting().then(function() {
        if (!self.fs) {
            self.importScripts('https://cdn.jsdelivr.net/npm/browserfs');
            BrowserFS.configure({ fs: 'IndexedDB', options: {} }, function (err) {
                if (err) {
                    console.log(err);
                } else {
                    self.fs = BrowserFS.BFSRequire('fs');
                    self.path = BrowserFS.BFSRequire('path');
                }
            });
        }
    });
}
self.addEventListener('install', loadDependecies);

self.addEventListener('activate', loadDependecies);

self.addEventListener('fetch', function (event) {
    event.respondWith(new Promise(function(resolve, reject) {
        if (local) {
            console.log('serving ' + path + ' from browserfs');
            if (!self.fs) {
                (function loop() {
                    if (!self.fs) {
                        setTimeout(loop, 400);
                    } else {
                        serve();
                    }
                })();
            } else {
                serve();
            }
        } else {
            if (event.request.cache === 'only-if-cached' && event.request.mode !== 'same-origin') {
                return;
            }
            //request = credentials: 'include'
            fetch(event.request).then(resolve).catch(reject);
        }
    }));
});

and when I didn't interact with the app for a while, open it again and then try to fetch local file It was keep loading probably because of the infinite loop, I've needed to reload the service worker by hand (using dev tools) to get the page.

So my question is how can I properly call importScripts to load BrowserFS in Service Worker?

like image 218
jcubic Avatar asked Nov 07 '22 05:11

jcubic


1 Answers

I've ended up with this code, let is not added to global scope so it should be safe:

self.importScripts('https://cdn.jsdelivr.net/npm/browserfs');
let path = BrowserFS.BFSRequire('path');
let fs = new Promise(function(resolve, reject) {
    BrowserFS.configure({ fs: 'IndexedDB', options: {} }, function (err) {
        if (err) {
            reject(err);
        } else {
            resolve(BrowserFS.BFSRequire('fs'));
        }
    });
});

self.addEventListener('install', self.skipWaiting);

self.addEventListener('activate', self.skipWaiting);

self.addEventListener('fetch', function (event) {
    event.respondWith(fs.then(function(fs) {
        return new Promise(function(resolve, reject) {
            var url = event.request.url;
            var m = url.match(/__browserfs__(.*)/);
            if (m) {
                var path = m[1];
                if (path === '') {
                    return redirect_dir();
                }
                console.log('serving ' + path + ' from browserfs');
                serve();
            } else {
                if (event.request.cache === 'only-if-cached' && event.request.mode !== 'same-origin') {
                    return;
                }
                //request = credentials: 'include'
                fetch(event.request).then(resolve).catch(reject);
            }
        });
    }));
});

EDIT it seems that this code also is wrong so I use this:

self.addEventListener('fetch', function (event) {
    let path = BrowserFS.BFSRequire('path');
    let fs = new Promise(function(resolve, reject) {
        BrowserFS.configure({ fs: 'IndexedDB', options: {} }, function (err) {
            if (err) {
                reject(err);
            } else {
                resolve(BrowserFS.BFSRequire('fs'));
            }
        });
    });
    ...
});

will see if this works. It may require to use importScripts in fetch.

like image 51
jcubic Avatar answered Nov 14 '22 10:11

jcubic