# Single Web Worker Example

## Introduction

This example is intended for beginners. However, I will assume that you have some basic knowledge about `Web development`, `JavaScript` and `IFC.js`.&#x20;

Also, please note that this part is only an explanation of the concepts. Take a look at the next chapter (Developer Guide) to see step by step instructions.

## Web Workers

### What are Web Workers?

JavaScript is a single-threaded environment, meaning multiple scripts cannot run at the same time [(1)](https://www.html5rocks.com/en/tutorials/workers/basics/). However, `Web Workers` makes it possible to run a script operation in a background thread [(2)](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API).

A `Web Worker` is a JavaScript script that runs in the background, independently of any other scripts, without affecting the performance of the page [(3)](https://www.w3schools.com/html/html5_webworkers.asp).

### What can Web Workers do?

`Web Workers` are a simple means for web content to run scripts in background threads. Once created, a worker can send messages to the JavaScript code that created it by posting messages to an event handler specified by that code [(4)](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers).

### I don't understand...

It's okay. Check out:

{% embed url="<https://www.w3schools.com/html/html5_webworkers.asp>" %}

## Using Web Workers

### How do I configure IFC.js to work with Web Workers?

Please note that `Web Workers` will not work straight out the box.

`Web Workers` use the [structured clone algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm) when you [post a message](https://developer.mozilla.org/en-US/docs/Web/API/Worker/postMessage).

Certain types, say `Functions`, are **NOT** supported by the [structured clone algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm). Therefore, we cannot build the entire `IFC Project` in a Web Worker.

### Why can't I build the entire IFC Project inside a Web Worker?

The `mainObject`, used in `src/ifc-project-builder/ifc-structure-builder.js`, contains some nasty stuff. The [structured clone algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm) cannot deal with that type of object.

Also, it's hard to use Three inside a web worker. See: <https://stackoverflow.com/a/52243600/14353202>

### How do I solve this?

I purpose that we (yes, you and me) use a dirty trick.

Let's:

1. Start a `Web Worker`
2. Run `loadIfcFileItems()` as usual
3. Run `constructProject()` without the `mainObject`
4. Exit the `Web Worker`
5. Append the `mainObject` (outside of the Web Worker)
6. Build the geometry (outside of the Web Worker)

### Okay, so how do I actually do this?

I am glad you asked. Take a look at `main.js`.

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

```javascript
function readFile(input) {
    const reader = new FileReader();
    reader.onload = () => {
        const ifcWorker = new Worker('worker.js');
        ifcWorker.postMessage(reader.result);
        ifcWorker.onmessage = function (e) {
          let structured = e.data; /
          structured.MainObject = mainObject;
          structured = buildGeometry(structured);
          scene.add(structured.MainObject);
        };
    };
    reader.readAsText(input.files[0]);
}
```

{% endcode %}

Notice how we use the `Web Worker` (line 5).\
We `post` the FileReader result into the worker.\
And, we get back the `structured` object (line 6).

Also, notice how we add back the `mainObject` in the snippet above.

Easy ey? :)

### A closer look at the Web Worker

The code inside the `Web Worker` is actually super easy:

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

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

{% endcode %}

We simply mimic the beginning of the original `loadIfc` function, in `src/IFC.js`.

#### Final Notes

Take a look at these commits:

* [Add Web Worker example](https://github.com/andrewisen/IFC.js-web-worker-example/commit/327abb2459a48fc468eabd1ee3b7a70c04fa6bba)
* [Add Config](https://github.com/andrewisen/IFC.js-web-worker-example/commit/f5d9ff76c9b90fa282eb88f1fc94b1bb3e8aa9e4)
* [Remove mainObject](https://github.com/andrewisen/IFC.js-web-worker-example/commit/d84a4864a8573c6d5cd2e67fef14439e701f453d)


---

# 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/web-worker-example/single-web-worker-example.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.
