Loading scripts in IndexedDB

How to make IndexedDB a library of functions for a Web or Electron application.

We want to store the following script in the database:

// Classical Fibonacci algorithm

var fibmax=16
var z=0

function fib(n) {
   if(n<=1) {
      z=n
   }   
   else {
      z=0+fib(n-1)+fib(n-2)
   }
   return z
}

alert("Script available")

The alert message is here only for the demonstration.

The script has a title, "Fibo" which serves as an indexing key.

1) Adding the script to the database

function addScript(dname, sname, scriptTitle, code) {
  return new Promise(function(resolve) {
    var r = window.indexedDB.open(dname)
      r.onupgradeneeded = function() {
        var idb = r.result
        var store = idb.createObjectStore(sname)
     }
     r.onsuccess = function() {
        var idb = r.result
        let tactn = idb.transaction(sname, "readwrite")
        var store = tactn.objectStore(sname)
        store.put(code, scriptTitle)
        resolve(idb)
     }
     r.onerror = function (e) {
       alert("Enable to access IndexedDB, " + e.target.errorCode)
     }    
  })
}

The database does not use a schema as is the case for importing JavaScript objects, so the put command has an extra parameter beside the code of the function, the title that serves as the indexing key.

The script is downloaded from a source file with the fetch command.

async function loadFile(fname, title) {
  var response = await fetch(fname)
  var code = await response.text()
  var idb = await addScript("Library", "LibStore", title, code)
  return idb
}

The database in the example is named "Library" and the storage table "LibStore".

2) Viewing the contents of the database

The script is found in the base from its title and the code obtained by the method get of IndexedDB.

function getCode(dname, sname, scriptTitle) {
  return new Promise(function(resolve) {
    var r = indexedDB.open(dname)
    r.onsuccess = function(e) {
      var idb = r.result
      let tactn = idb.transaction(sname, "readonly")
      let store = tactn.objectStore(sname)
      let code = store.get(scriptTitle)
      code.onsuccess = function() {
        resolve(code.result)
      }
      tactn.oncomplete = function() {
        idb.close()
      }
    }
  })
}

The following function displays the title and code in the HTML page.

async function show() {
  var title = "Fibo"
  var code = await getCode("Library", "LibStore", title)
  document.getElementById("title").innerHTML = title
  document.getElementById("code").innerHTML = code
}

To show them, we place the title in a <div> tag and the code in a <pre> tag

The code is just displayed. If we want to make it active, we will put it in a <script> tag instead.

3) Launching the script

It is placed in this tag:

<script id="script"></script>

The script is made active and run:

async function runScript() {
  var title = "Fibo"
  var code = await getCode("Library", "LibStore", title)
  document.getElementById("script").innerHTML = code

  var result = document.getElementById("result")
  for(let i=2; i< 15; i++) {
     result.innerHTML += fib(i) + "</br>"
  }    
}

As soon as the code is inserted in the <script> tag, it becomes active and the alert command displays the message "Script available". The fib function waits to be called, which the loop does above, the result of the call being displayed in a new tag.

The complete source code is available in an archive to download.

You can test the demo locally with Firefox or online with any browser:

See also: