Skip to content
This repository has been archived by the owner on May 29, 2023. It is now read-only.

Commit

Permalink
feat: added service and base classes
Browse files Browse the repository at this point in the history
  • Loading branch information
IKatsuba committed Sep 25, 2020
1 parent 149bb8e commit 3dfd75e
Show file tree
Hide file tree
Showing 10 changed files with 147 additions and 1 deletion.
2 changes: 2 additions & 0 deletions projects/demo/src/app/app.browser.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
import {NgModule} from '@angular/core';
import {FormsModule} from '@angular/forms';
import {BrowserModule} from '@angular/platform-browser';
import {WebWorkerModule} from '@ng-web-apis/workers';
import {AppComponent} from './app.component';
import {AppRoutingModule} from './app.routes';

Expand All @@ -17,6 +18,7 @@ import {AppRoutingModule} from './app.routes';
FormsModule,
BrowserModule.withServerTransition({appId: 'demo'}),
AppRoutingModule,
WebWorkerModule,
],
declarations: [AppComponent],
providers: [
Expand Down
7 changes: 7 additions & 0 deletions projects/demo/src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<form (ngSubmit)="workerThread.next(input.value)">
<input #input />
<button type="submit">Send</button>
<button type="button" (click)="workerThread.complete()">Complete</button>
</form>

{{ workerThread | async | json }}
11 changes: 10 additions & 1 deletion projects/demo/src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
import {ChangeDetectionStrategy, Component} from '@angular/core';
import {WebWorker, WebWorkerExecutor} from '@ng-web-apis/workers';

@Component({
selector: 'main',
templateUrl: './app.component.html',
styleUrls: ['./app.component.less'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent {}
export class AppComponent {
public workerThread: WebWorker<string, string>;

constructor(webWorkerExecutor: WebWorkerExecutor) {
this.workerThread = webWorkerExecutor.execute((result: string) =>
Promise.resolve(`Message from worker: ${result}`),
);
}
}
4 changes: 4 additions & 0 deletions projects/workers/src/public-api.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/**
* Public API Surface of @ng-web-apis/workers
*/
export * from './web-worker/web-worker.module';
export * from './web-worker/types/web-worker-function';
export * from './web-worker/services/web-worker-executor.service';
export * from './web-worker/classes/web-worker';
7 changes: 7 additions & 0 deletions projects/workers/src/web-worker/classes/any-next-subject.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {Subject} from 'rxjs';

export class AnyNextSubject<T> extends Subject<T> {
next(value?: any) {
super.next(value);
}
}
78 changes: 78 additions & 0 deletions projects/workers/src/web-worker/classes/web-worker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import {fromEvent} from 'rxjs';
import {takeWhile} from 'rxjs/operators';
import {WebWorkerFunction} from '../types/web-worker-function';
import {AnyNextSubject} from './any-next-subject';

export class WebWorker<T, R> extends AnyNextSubject<R> {
private worker!: Worker;

private static createFnUrl(fn: WebWorkerFunction): string {
const script = `
self.addEventListener('message', function(e) {
var result = ((${fn.toString()}).call(null, e.data));
if(result && [typeof result.then, typeof result.catch].every(function (type) {return type === 'function'})){
result.then(function(res){
postMessage({result: res});
}).catch(function(error){
postMessage({error: error});
})
} else {
postMessage(result);
}
});
`;

const blob = new Blob([script], {type: 'text/javascript'});

return URL.createObjectURL(blob);
}

public static fromFunction<T, R>(
fn: WebWorkerFunction<T, R>,
options?: WorkerOptions,
): WebWorker<T, R> {
return new WebWorker<T, R>(WebWorker.createFnUrl(fn), options);
}

constructor(private url: string, options?: WorkerOptions) {
super();

try {
this.worker = new Worker(url, options);
} catch (e) {
this.error(e);
}

fromEvent<MessageEvent>(this.worker, 'message')
.pipe(takeWhile(() => !this.isStopped))
.subscribe(event => {
if (event.data) {
if (event.data.hasOwnProperty('error')) {
this.error(event.data.error);
} else if (event.data.hasOwnProperty('result')) {
super.next(event.data.result);
} else {
super.next();
}
}
});

fromEvent<ErrorEvent>(this.worker, 'error')
.pipe(takeWhile(() => !this.isStopped))
.subscribe(event => {
this.error(event.error);
});
}

complete() {
this.worker.terminate();
URL.revokeObjectURL(this.url);
super.complete();
}

next(value?: T) {
if (!this.isStopped) {
this.worker.postMessage(value);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import {TestBed} from '@angular/core/testing';

import {WebWorkerExecutor} from './web-worker-executor.service';

describe('WebWorkerExecutorService', () => {
beforeEach(() => TestBed.configureTestingModule({}));

it('should be created', () => {
const service: WebWorkerExecutor = TestBed.get(WebWorkerExecutor);

expect(service).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {inject, Injectable, InjectFlags} from '@angular/core';
import {WebWorker} from '../classes/web-worker';
import {WebWorkerFunction} from '../types/web-worker-function';
import {WebWorkerModule} from '../web-worker.module';

@Injectable({
providedIn: WebWorkerModule,
useFactory(): WebWorkerExecutor {
const instance = inject(WebWorkerExecutor, InjectFlags.Optional);

return instance || new WebWorkerExecutor();
},
})
export class WebWorkerExecutor {
execute<T, R>(fn: WebWorkerFunction<T, R>, options?: WorkerOptions): WebWorker<T, R> {
return WebWorker.fromFunction<T, R>(fn, options);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type WebWorkerFunction<T = any, R = any> = (data: T) => R | PromiseLike<R>;
7 changes: 7 additions & 0 deletions projects/workers/src/web-worker/web-worker.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {CommonModule} from '@angular/common';
import {NgModule} from '@angular/core';

@NgModule({
imports: [CommonModule],
})
export class WebWorkerModule {}

0 comments on commit 3dfd75e

Please sign in to comment.