Angular8 Web Workers
Web workers 使 JavaScript 应用程序能够运行 CPU 密集型后台让应用主线程专注于UI的流畅运行。 Angular 支持在应用程序中包含 Web 工作者。让我们编写一个简单的 Angular 应用程序并尝试使用 Web Worker。
使用以下命令创建一个新的 Angular 应用程序-
cd /go/to/workspace
ng new web-worker-sample
使用以下命令运行应用程序-
cd web-worker-sample
npm run start
使用以下命令添加新的网络工作者-
ng generate web-worker app
上述命令的输出如下-
CREATE tsconfig.worker.json (212 bytes)
CREATE src/app/app.worker.ts (157 bytes)
UPDATE tsconfig.app.json (296 bytes)
UPDATE angular.json (3776 bytes)
UPDATE src/app/app.component.ts (605 bytes)
这里,
app 指的是要创建的网络工作者的位置。
Angular CLI 将生成两个新文件 tsconfig.worker.json 和 src/app/app.worker.ts 并更新三个文件 tsconfig.app.json、angular.json 和 src/app/app.component.ts文件。
让我们检查更改-
// tsconfig.worker.json
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/worker",
"lib": [
"es2018",
"webworker"
],
"types": []
},
"include": [
"src/**/*.worker.ts"
]
}
这里,
tsconfig.worker.json 扩展了 tsconfig.json 并包含编译 Web Worker 的选项。
// tsconfig.app.json [only a snippet]
"exclude": [
"src/test.ts",
"src/**/*.spec.ts",
"src/**/*.worker.ts"
]
这里,
基本上,它从编译中排除所有工作线程,因为它具有单独的配置。
// angular.json (only a snippet) "webWorkerTsConfig": "tsconfig.worker.json"
这里,
angular.json 包含 Web Worker 配置文件 tsconfig.worker.json。
// src/app/app.worker.ts
addEventListener('message', ({ data }) => {
const response = `worker response to ${data}`;
postMessage(response);
});
这里,
一个网络工作者被创建。 Web worker 基本上是一个函数,当消息事件被触发时会被调用。 Web Worker 将接收调用者发送的数据,对其进行处理,然后将响应发送回调用者。
// src/app/app.component.ts [only a snippet]
if (typeof Worker !== 'undefined') {
// Create a new
const worker = new Worker('./app.worker', { type: 'module' });
worker.onmessage = ({ data }) => {
console.log(`page got message: ${data}`);
};
worker.postMessage('hello');
} else {
// Web Workers are not supported in this environment.
// You should add a fallback so that your program still executes correctly.
}
这里,
AppComponent 创建一个新的 worker 实例,创建一个回调函数来接收响应,然后将消息发布给 worker。
重新启动应用程序。由于 angular.json 文件发生了变化,Angular runner 不会监视该文件,因此需要重新启动应用程序。否则,Angular 不会识别新的 Web Worker 并且不会编译它。
让我们创建 Typescript 类 src/app/app.prime.ts 来查找第 n 个素数。
export class PrimeCalculator
{
static isPrimeNumber(num : number) : boolean {
if(num == 1) return true;
let idx : number = 2;
for(idx = 2; idx < num / 2; idx++)
{
if(num % idx == 0)
return false;
}
return true;
}
static findNthPrimeNumber(num : number) : number {
let idx : number = 1;
let count = 0;
while(count < num) {
if(this.isPrimeNumber(idx))
count++;
idx++;
console.log(idx);
}
return idx-1;
}
}
这里,
isPrimeNumber 检查给定的数字是否为素数。
findNthPrimeNumber 查找第 n 个质数。
将新建的质数类导入到src/app/app.worker.ts中,改变web worker的逻辑,找到第n个质数。
/// <reference lib="webworker" />
import { PrimeCalculator } from './app.prime';
addEventListener('message', ({ data }) => {
// const response = `worker response to ${data}`;
const response = PrimeCalculator.findNthPrimeNumber(parseInt(data));
postMessage(response);
});
更改
AppComponent 并包含两个函数,
find10thPrimeNumber 和
find10000thPrimeNumber。
import { Component } from '@angular/core';
import { PrimeCalculator } from './app.prime';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'Web worker sample';
prime10 : number = 0;
prime10000 : number = 0;
find10thPrimeNumber() {
this.prime10 = PrimeCalculator.findNthPrimeNumber(10);
}
find10000thPrimeNumber() {
if (typeof Worker !== 'undefined') {
// Create a new
const worker = new Worker('./app.worker', { type: 'module' });
worker.onmessage = ({ data }) => {
this.prime10000 = data;
};
worker.postMessage(10000);
} else {
// Web Workers are not supported in this environment.
// You should add a fallback so that your program still executes correctly.
}
}
}
这里,
find10thPrimeNumber 直接使用 PrimeCalculator。但是,find10000thPrimeNumber 将计算委托给 web worker,后者又使用 PrimeCalculator。
更改 AppComponent 模板 src/app/app.commands.html 并包含两个选项,一个用于查找第 10 个质数,另一个用于查找第 10000 个质数。
<h1>{{ title }}</h1>
<div>
<a href="#" (click)="find10thPrimeNumber()">Click here</a> to find 10th prime number
<div>The 10<sup>th</sup> prime number is {{ prime10 }}</div> <br/>
<a href="#" (click)="find10000thPrimeNumber()">Click here</a> to find 10000th prime number
<div>The 10000<sup>th</sup> prime number is {{ prime10000 }}</div>
</div>
这里,
查找第 10000 个质数需要几秒钟的时间,但不会影响其他进程,因为它使用的是 web worker。尝试先找到第 10000 个素数,然后再找到第 10 个素数。
由于网络工作者正在计算第 10000 个素数,因此 UI 不会冻结。我们可以同时检查第 10 个质数。如果我们没有使用 web worker,我们就无法在浏览器中做任何事情,因为它正在主动处理第 10000 个质数。
申请结果如下-
应用程序的初始状态。
单击并尝试找到第 10000 个质数,然后尝试找到第 10 个质数。该应用程序非常快地找到第 10 个质数并显示它。应用程序仍在后台处理以查找第 10000 个质数。
两个过程都完成了。
Web worker 通过在后台进行复杂的操作来增强 Web 应用程序的用户体验,在 Angular 应用程序中也很容易做到。