DEV Community

Cover image for Observable Web Workers with Angular (8) - Introduction

Observable Web Workers with Angular (8) - Introduction

Zak Henry on June 16, 2019

tl;dr Web Workers are awesome and Angular CLI now supports them natively. Unfortunately, the Web Worker API is not Angular-like and ther...
Collapse
 
johncarroll profile image
John Carroll • Edited

FYI: you link to the NPM package several places in the article, but the package.json is apparently missing a link to the associated git repo.

I can't speak for everyone obviously, but I have no interest in npmjs.org links. I only use them to find the associated git repo. For anyone else looking for the git repo, you can find it here: github.com/cloudnc/observable-webw... (the last link in the article references it).

(also, thanks for open-sourcing your work! Looks super useful)

Collapse
 
zakhenry profile image
Zak Henry

Thanks for the tip John, I have actually already fixed this however it hasn't been released due to the semantic release program computing the change was immaterial and didn't warrant a version bump, so this fix will go out with the next addition to the library. I'll see if there is anything obvious I can fix up to ensure it gets out as this is kinda annoying I agree.

Collapse
 
johncarroll profile image
John Carroll • Edited

Dunno what your pipeline is, but I remember running into something like this with lerna and I was able to make use of an option (--force ? --force-publish ?) to force out an otherwise identical patch release.

Collapse
 
bboyle profile image
Ben Boyle

This sounds great Zak, thanks for sharing!

I'm confused though. I think I followed these steps right, but the worker threads aren't being terminated. Did I miss something? github.com/bboyle/observable-workers

Collapse
 
bboyle profile image
Ben Boyle

seems to be the version of observable-workers. I see the worker threads being terminated if I use version 3.0.1. doesn't seem to be an issue with the advanced blog posts

Collapse
 
jzabinskidolios profile image
jzabinski-dolios • Edited

You have to explicitly call subscription.unsubscribe() in order for the workers to be torn down. In other words, this:

  runWorker() {
    const input$: Observable<string> = of('hello');

   fromWorker<string, string>(
      () => new Worker(new URL('./app.worker', import.meta.url), { type: 'module' }),
      input$
    ).subscribe((message) => {
      console.log(`Got message`, message);
    });
Enter fullscreen mode Exit fullscreen mode

Really needs to be this:

subscription = new Subscription();

  runWorker() {
    const input$: Observable<string> = of('hello');

    this.subscription.add(fromWorker<string, string>(
      () => new Worker(new URL('./app.worker', import.meta.url), { type: 'module' }),
      input$
    ).subscribe((message) => {
      console.log(`Got message`, message);
      ==> this.subscription.unsubscribe(); <==
    })
    );
Enter fullscreen mode Exit fullscreen mode
Collapse
 
jzabinskidolios profile image
jzabinski-dolios

Just went through this helpful introduction. As of 2022, there seem to be just a few differences to highlight:

  1. ObservableWorker has been deprecated. runWorker is intended to replace it, like this:
import { DoWork, runWorker } from 'observable-webworker';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

export class DemoWorker implements DoWork<string, string> {
  public work(input$: Observable<string>): Observable<string> {
    return input$.pipe(map((data) => `worker response to ${data}`));
  }
}

runWorker(DemoWorker);
Enter fullscreen mode Exit fullscreen mode
  1. If you run this code in a browser, you will probably notice that the worker thread continues to stick around after it has run. This is because the workers are kept as part of the inner workings of fromWorker. It will terminate those workers when the subscription is unsubscribed (not just when the observable emits Complete). So this code:
  runWorker() {
    const input$: Observable<string> = of('hello');

   fromWorker<string, string>(
      () => new Worker(new URL('./app.worker', import.meta.url), { type: 'module' }),
      input$
    ).subscribe((message) => {
      console.log(`Got message`, message);
    });
  }
Enter fullscreen mode Exit fullscreen mode

Should really be this code:

--> subscription = new Subscription();

  runWorker() {
    const input$: Observable<string> = of('hello');

-->     this.subscription.add(fromWorker<string, string>(
      () => new Worker(new URL('./app.worker', import.meta.url), { type: 'module' }),
      input$
    ).subscribe((message) => {
      console.log(`Got message`, message);
-->      this.subscription.unsubscribe();
    })
    );
  }
Enter fullscreen mode Exit fullscreen mode
Collapse
 
andrewa40539253 profile image
Andrew Allen

I would love to know more about the inner workings. Btw you and maxime1992 always seem to ask the same question I research. Thank you for all the public info you output

Collapse
 
shivenigma profile image
Vignesh M

Man, You can't possibly know how happy I am to see this library. Going to try it over the weekend and on next week possibly in a project where I am currently performance optimizing.

Collapse
 
johnasbroda profile image
Ferenczfi Jonatán

Looks really nice and interesting. Im definitely going to give it a look.

Collapse
 
achimoraites profile image
Achilles Moraites

Well done !!!
Thanks for sharing!!!

Collapse
 
narshe1412 profile image
Manuel

Excellent post. Can you please include, either at the top or bottom (or both), a link to the follow-up article?
Thanks!

Collapse
 
zakhenry profile image
Zak Henry

Hey Manual, thanks for the support! DEV now automagically adds this to the beginning of all articles that are marked as a part of a series :)