# 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.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://bimwhale.gitbook.io/ifc-js/saving-the-scene/indexeddb.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
