> For the complete documentation index, see [llms.txt](https://bimwhale.gitbook.io/ifc-js/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://bimwhale.gitbook.io/ifc-js/saving-the-scene/indexeddb.md).

# IndexedDB

## Introduction

The IndexedDB API is mostly asynchronous.  The API doesn't give you data by returning values; instead, you have to pass a [**callback function.**](https://developer.mozilla.org/en-US/docs/Glossary/Callback_function)

{% code title="examples/web-worker/main.js" %}

```javascript
 const cb = () => { // This is a callback fucntion }
```

{% endcode %}

{% hint style="info" %}
You don't "store" a value into the database, or "retrieve" a value out of the database through synchronous means. &#x20;
{% endhint %}

Instead, you "request" that a database operation happens.

{% code title="examples/web-worker/main.js" %}

```javascript
  let indexedDB = new IndexedDB();
  const cb = () => {
      indexedDB.get()
  };
  indexedDB.init(cb);
}
```

{% endcode %}

You get notified by a DOM event when the operation finishes, and the type of event you get lets you know if the operation succeeded or failed.  This sounds a little complicated at first, but there are sanity measures baked in.  It's not that different from the way that XMLHttpRequest works.

## Behind the Scenes

Let's take a look at `indexed-db.js`. We have very simple IndexedDB object.

{% code title="examples/web-worker/assets/js/indexed-db.js" %}

```javascript
function IndexedDB() {
    const name = 'ifc-js';
    const version = 1;
    const transactionName = 'scene';
    var database;
    return {
        // Todo
    }
}
```

{% endcode %}

As we discussed earlier, we "request" that a database operation happens. The initialization looks like this. Don't focus too much on the code. Simply note that we have a `request`, and it can either be&#x20;

* onupgradeneeded
* onsucess
* onerror

{% code title="examples/web-worker/assets/js/indexed-db.js" %}

```javascript
  init: function (cb) {
      var request = indexedDB.open(name, version);
      
      request.onupgradeneeded = function (event) {
          // DO STUFF
      };
      
      request.onsuccess = function (event) {
          // DO STUFF
      };
      
      request.onerror = function (event) {
          // DO STUFF
      };
    },
```

{% endcode %}

Our code looks like this if we have successfully initilized the IndexedDB. Notice how the callback function, cb(), is used.

{% code title="examples/web-worker/assets/js/indexed-db.js" %}

```javascript
init: function (cb) {
    var request = indexedDB.open(name, version);
    request.onsuccess = function (event) {
        database = event.target.result;
        cb();
    };
},
```

{% endcode %}

## Get

Notice that we have nested callback function.&#x20;

{% code title="examples/web-worker/assets/js/indexed-db.js" %}

```javascript
function readFile(input) {
    const { name, lastModified, size } = input.files[0];
    let myIfcFile = new IfcFile(name, lastModified, size);
    let indexedDB = new IndexedDB();
    
    const cb = () => {
        indexedDB.get(myIfcFile.name, function (ifcFile) {
            // Do stuff
        });
    };
    indexedDB.init(cb);
}
```

{% endcode %}

We start with `indexedDB.init(cb)` at row 11. Then, if the databased was initlized, we call `indexedDB.get(...)`. The second parameter is another callback function. I.e. this part:

{% code title="examples/web-worker/main.js" %}

```javascript
function (ifcFile) {
    // Do stuff
});
```

{% endcode %}

At this point, the database might or might not exist. We need to check that.

{% code title="examples/web-worker/main.js" %}

```javascript
function (ifcFile) {
    simpleCheck(ifcFile) ? parseIfcFile(input, myIfcFile) : rebuildScene(ifcFile.structured);
});
```

{% endcode %}

I used a simple [ternary operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator) to perfom this check.

{% code title="examples/web-worker/assets/js/simple-check.js  /" %}

```javascript
function simpleCheck(ifcFile) {
    return ifcFile === undefined ? true : false;
}
```

{% endcode %}

## Set

Let's explore `single-worker.js`. Please note that the `single` and `multi` web workers operates in the same way.

{% code title="examples/web-worker/worker/single-worker.js" %}

```javascript
onmessage = (e) => {
    const { result: ifcData, myIfcFile } = e.data;
    const loaded = IFCjs.loadIfcFileItems(ifcData);
    const structured = IFCjs.constructProject(loaded);
    saveStructured(structured, myIfcFile);
    postMessage(structured);
};
```

{% endcode %}

Before we `post` our structure, we save it - see line 5. Let's open `save-structured.js`. This snippet works like the last one. Notice how we use the callback function.&#x20;

{% code title="examples/web-worker/worker/save/save-structured.js" %}

```javascript
const saveStructured = (structured, myIfcFile) => {
    structured = { structured, MetaData: myIfcFile };
    let indexedDB = new IndexedDB();
    const cb = () => {
        indexedDB.set(structured, myIfcFile.name);
    };
    indexedDB.init(cb);
};
```

{% endcode %}

To clarify, we start by initlizing the indexedDB. Then we set (save) the structured data.
