运行 主线程中的一个模块,否则 Angular webworker 项目

Run one module in main thread in otherwise Angular webworker project

让我们在 angular 中创建一个项目。出于性能原因,我们希望该应用程序在 webworkers 中 运行,这没关系,因为 Angular 团队有可能做到这一点。


我们的应用程序需要实现一个 DOM 操作库(google 地图)。因此,我们需要在主线程上创建此模块 运行,其中可以进行 DOM 操作。然而,我们仍然希望在 webworker 中完成所有繁重的工作。

为了减少这个问题,我将对外部库的所有调用都包含在一个文件中。为方便起见,此文件是模块的服务。

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 => { ... })
    }
}

template.html只包含<content></content>。该组件从外部库请求地图元素服务,它是一个 div,然后通过 renderer.appendChild(element.nativeElement, div) 添加这个 div。函数 renderer.appendChild 是安全的,但我不确定 DOM 元素是否能够传递给 worker。

要回答的问题:


备注:

我认为 angular 没有默认支持 运行 网络工作者中的一些模块和主线程中的一些模块。 angular 中可用的默认支持是 运行 使用 "platform-webworker" 和 "platform-werbworker-dynamic" 模块的 Web 工作线程中的所有业务逻辑(组件和服务)。 要使用此解决方案,您需要确保您的应用程序在您的组件和服务中没有对 window、dom、文档等的任何直接引用。

如果很难修改现有应用程序以使其与 web worker 兼容,您仍然可以使用 web worker 运行在 web 中 cpu 密集 code/logic工作线程和应用程序的其余部分可以在主线程中保持 运行ning。

这里有一个演示文稿,讨论如何做到这一点: Web Workers In Your Angular Application

演示文稿中示例的源代码 Angular 5Angular 6

希望这对您有所帮助。