Akxe
Akxe

Reputation: 11485

Run one module in main thread in otherwise Angular webworker project

Let's have a project in angular. For performance reasons, we want the app to run in webworkers, this is okay as Angular team have a possibility to do it.


Our application needs want to implement a DOM manipulating library (google maps). We therefor need to make this module run on main thread, where DOM manipulation is possible. However we still want to do all of the heavy work in a webworker.

To minify this problem I contained all call to the external library to a single file. For convenience this file is module's service.

map
 - component.ts
 - service.ts
 - module.ts
 - template.html
 - styles.css

export class MapComponent implements OnInit, OnDestroy {
    constructor(private mapService: MapService, element: ElementRef, renderer: Renderer2)
        this.mapService.element.then(map => {
            renderer.appendChild(element.nativeElement, map)
        })
    }
}

@Injectable()
export class MapService {
    private static worker = new Worker('./worker.js')

    public map: google.maps.Map
    public element: Promise<Element>

    constructor(private http: Http) {
        const div = document.createElement('div')
        this.map = new google.maps.Map(div, { ... })
        this.element = new Promise(resolve => {
            //  Fetch google map div element as soon as it is availe
            google.maps.event.addDomListenerOnce(this.map, 'idle', () => {
                resolve(this.map.getDiv())
            })
        })
        MapService.worker.postMessage({ name: 'init', data: ... }])
        MapService.worker.addEventListener('message', event => { ... })
    }
}

The template.html only contains <content></content>. The component asks service for map element from external library, it is a div, this div is then added via renderer.appendChild(element.nativeElement, div). The function renderer.appendChild is safe, but I am not sure if the DOM element, would be able to pass be passed to worker.

Questions to answer:


Notes:

Upvotes: 2

Views: 1643

Answers (1)

Suresh Patidar
Suresh Patidar

Reputation: 64

I think angular doesn't have default support for running some of module in web worker and some in main thread. The default support available in angular is to run all your business logic (component and services) in web worker thread using "platform-webworker" and "platform-werbworker-dynamic" modules. To work with this solution you need to make sure that your application does not have any direct references to window, dom, document etc in your component and services.

If it is difficult to modify existing application to make it compatible for web worker, you can still use web worker for running some of your cpu intensive code/logic in web worker thread and rest of the application can keep running in main thread.

Here is a presentation that talks about, how to do this: Web Workers In Your Angular Application

Source code of the examples from the presentation for Angular 5 and Angular 6

Hope you will find this helpful.

Upvotes: 2

Related Questions