0

I am on Chrome Version 57.0.2987.110 (64-bit) on MacOS/OSX 12.3 Sierra,

I managed to get a service worker working, but I must say I am new at this.

I now try to get it to use an IndexedDB and store data in it.

It fetches data from a local web server in http and retrieve it without problem in json format.

The data format is :

[{"id":"1", "...":"...", ...},
 {"id":"2", "...":"...", ...},
 {"id":"3", "...":"...", ...},
 ...
 {"id":"n", "...":"...", ...}]

it then adds the data to an IndexedDB without problem apparently because the onsuccess callback is triggered ...

entityObjectStore.add success : Event {isTrusted: true, type: "success", target: IDBRequest, currentTarget: IDBRequest, eventPhase: 2…}

But it does not appear in the Chrome dev tools!

Here is my service worker:

self.addEventListener('install',function(event)
    {
    event.waitUntil(
        (new Promise(function(resolve,reject)resolve()}))
        .then(function()
            {return self.skipWaiting();}));
    });

self.addEventListener('activate', function(event)
    {
    event.waitUntil(
        (new Promise(function(resolve,reject){resolve()}))
        .then(function() {return self.clients.claim();}));
    });

self.addEventListener('message', function(event)
    {
    if(event.data.command=="data.load")
        {
        var options = event.data.options
        var url = new URL(event.data.host+options.source);
        var parameters = {entity:options.name,
                          options:encodeURIComponent(options.options)};
        Object.keys(parameters)
            .forEach(key => url.searchParams.append(key,
                                                    parameters[key]))
        fetch(url).then(function(response)
            {
            if(response.ok)
                {
                response.json().then(function(data_json)
                    {
                    var entityData = data_json;
                    var request = indexedDB.open(options.name);
                    request.onerror = function(event)
                        {
                        console.log("indexedDB.open error :",event);
                        };
                    request.onsuccess = function(event)
                        {
                        console.log("indexedDB.open success :",event)
                        var db = event.target.result;
                        }
                    request.onupgradeneeded = function(event)
                        {
                        console.log("indexedDB.open upgrade :",event)
                        var db = event.target.result;
                        db.createObjectStore(options.options.id, { keyPath: "id" });
                        objectStore.transaction.oncomplete = function(event)
                            {
                            var entityObjectStore = db.transaction(options.options.id, "readwrite").objectStore(options.options.id);
                            for (var i in entityData)
                                {
                                var addRequest = entityObjectStore.add(entityData[i]);
                                addRequest.onerror = function(event)
                                    {
                                    console.log("entityObjectStore.add error :",event);
                                    };
                                addRequest.onsuccess = function(event)
                                    {
                                    console.log("entityObjectStore.add success :",event);
                                    };
                                }
                            }
                        };

                    });
                }
            });
        }
    else if(event.data.command=="data.get")
        {
        var command = event.data;
        var request = indexedDB.open(command.domain);
        request.onerror = function(event)
            {
            console.log("indexedDB.open error :",event);
            };
        request.onsuccess = function(event)
            {
            console.log("indexedDB.open success :", event)
            var db = event.target.result;
            var transaction = db.transaction([command.domain]);
            var objectStore = transaction.objectStore(command.entity);
            var request = objectStore.get(command.id);
            request.onerror = function(event)
                {
                console.log("objectStore.get error :",event);
                };
            request.onsuccess = function(event)
                {
                console.log("objectStore.get success :",event);
                console.log("request.result=" + request.result);
                };          
            }
        }
    });

Here is the HTML file I use with it :

<!DOCTYPE html>
<html>
    <head>
        <title>My service worker app</title>
    </head>
    <body>
        <button id="update">Update</button>
        <div id="log"></div>
        <script type="text/javascript">
        function sendMessage(message)
            {
            return new Promise(function(resolve, reject)
                {
                var messageChannel = new MessageChannel();
                messageChannel.port1.onmessage = function(event)
                    {
                    if (event.data.error)
                        {
                        reject(event.data.error);
                        }
                    else
                        {
                        resolve(event.data);
                        }
                    };

                });
            }
            if (navigator.serviceWorker.controller)
                {
                var url = navigator.serviceWorker.controller.scriptURL;
                var initData =  [
                                {
                                name:"my_entity_type",
                                source:"/webapp/data",
                                options:{id:"my_entity_type_id"}
                                }
                                ]
                for(var dataIndex in initData)
                    {
                    var data = initData[dataIndex]
                    sendMessage({
                                 command:"data.load",
                                 host: document.location.origin,
                                 options: data
                                 });
                    }
                }
            else
                {
                navigator.serviceWorker.register('/webapp/lt_sw.js')
                    .then(function(registration)
                        {
                        debug('Refresh to allow ServiceWorker to control this client', 'onload');
                        debug(registration.scope, 'register');
                        });
                }

    navigator.serviceWorker.addEventListener('controllerchange', 
    function() 
        {
        var scriptURL = navigator.serviceWorker.controller.scriptURL;
        debug(scriptURL, 'oncontrollerchange');
        });

    document.querySelector('#update').addEventListener('click', 
    function() 
        {
        navigator.serviceWorker.ready.then(function(registration)
            {
            registration.update()
                .then(function()
                    {
                    console.log('Checked for update');
                    })
                .catch(function(error)
                    {
                    console.error('Update failed', error);
                    });
                });
            });

        function debug(message, element)
            {
            var target = document.querySelector('#log');
            console.log(element,":",message)
            target.textContent = message;
            }
        </script>
    </body>
</html>

Any idea about what I am, doing wrong?

Edit 1:

I modified the script in the html file so that update mechanism sends another message to the service worker asking for data :

    document.querySelector('#update').addEventListener('click', 
    function() 
        {
        navigator.serviceWorker.ready.then(function(registration)
            {
            registration.update()
                .then(function()
                    {
                    console.log('Checked for update');
                    sendMessage({
                        command:"data.get",
                        domain:"database_name",
                        entity: "my_entity_type",
                        id: "my_entity_id"
                        });
                    })
                .catch(function(error)
                    {
                    console.error('Update failed', error);
                    });
                });
            });

And I added the following line:

    indexedDB.webkitGetDatabaseNames().onsuccess = function(sender,args){ console.log("data.get all dbs:",sender.target.result); };

Just at the beginning of the data look up part:

    else if(event.data.command=="data.get")
        {

To list all the IndexedDBs on Chrome as explained here : https://stackoverflow.com/a/15234833/2360577 And I get all the databases I created previously!

data.get all dbs: DOMStringList {0: "db1", 1: "db2", 2: "db3", 3: "db4", length: 4}

Then I proceeded to list all ObjectStores in these dbs, also as explained in the previous link, by adding the following line :

indexedDB.open(<databaseName>).onsuccess = function(sender,args) 
{"<databaseName>'s object stores",console.log(sender.target.result.objectStoreNames); };

And apart for one, where the data is processed and apparently does not work, they all had one object store with the same name as the db that contains it as expected ...

db1's object stores DOMStringList {0: "db1", length: 1}
db2's object stores DOMStringList {length: 0}
db3's object stores DOMStringList {0: "db3", length: 1}
db4's object stores DOMStringList {0: "db4", length: 1} 

Then I had a look inside the object stores ...

indexedDB.open("db3").onsuccess = function(event)
{event.target.result.transaction(["db3"]).objectStore("db3")
    .getAll().onsuccess = function(event)
    {console.log("objectStore.getAll() success :",event.target.result)};};

And the entries are there as expected! But not in Application/Storage ...

Edit 2:

The error for db2 was apparently that I did not refresh the data in the database ... this part works now ...

Edit 3:

The answer was as simple as closing and reopening the dev tools ... like @wOxxOm suggested ...

Community
  • 1
  • 1
Ailete619
  • 194
  • 1
  • 18

2 Answers2

1

You could also check the "Update on reload" button and try hard reset ctrl/shift+f5 to the same effect as @wOxxOm mentioned. enter image description here

Nemanja Milosavljevic
  • 1,251
  • 18
  • 33
1

It works for me if I close DevTools and open again. Did you try that?

Nuno
  • 3,082
  • 5
  • 38
  • 58