Search code examples
angulartypescriptweb-worker

How to terminate set of web workers from the main thread in an angular app?


I'm developing an angular app that creates several web workers and do separate works in the worker threads. My application reads a file input by a button click and then creates new Workers according to the [array.length] given inside the file. It works well. Now, what I need to do is terminate all the web workers by clicking a stop button. Below is the two methods that I used in two button clicks.

public i = 0;
public file: any;
public noOfOrders: number;
private worker: Worker;

public uploadDocument(): void {
    const fileReader = new FileReader();
    fileReader.onload = (e) => {
        const k = JSON.parse(fileReader.result.toString());
        this.noOfOrders = Math.round(k.orders_per_second / k.credentials.length);

        if (typeof Worker !== 'undefined') {
            while (this.i < k.credentials.length) {
                this.worker = new Worker('./app.worker', { type: 'module' });
                      this.worker.onmessage = ({ data }) => {
                        console.log(data + k.credentials.length);
                      };
                      this.worker.postMessage({ data: k.credentials[this.i], orders: this.noOfOrders });
                      this.i++;
            }
        }
    };
    fileReader.readAsText(this.file);
}

public stop(): void {                    // this method only terminates the final worker thread
    this.worker.terminate();
}

Solution

  • You are overwriting the same worker every time, that's why you can only terminate the last one.

    Instead, store them in an array of workers and call terminate() on all of them. Something like this:

      public i = 0;
      public file: any;
      public noOfOrders: number;
      private workers: Worker[];
    
      public uploadDocument(): void {
          const fileReader = new FileReader();
          fileReader.onload = (e) => {
              const k = JSON.parse(fileReader.result.toString());
              this.noOfOrders = Math.round(k.orders_per_second / k.credentials.length);
    
              if (typeof Worker !== 'undefined') {
                  while (this.i < k.credentials.length) {
                      const worker = new Worker('./app.worker', { type: 'module' });
                      worker.onmessage = ({ data }) => {
                        console.log(data + k.credentials.length);
                      };
                      worker.postMessage({ data: k.credentials[this.i], orders: this.noOfOrders });
                      this.workers.push(worker);
                      this.i++;
                  }
              }
          };
          fileReader.readAsText(this.file);
      }
    
      public stop(): void {
        this.workers.forEach(w => w.terminate());
      }