Last update on Saturday, July 22nd 2017

How to Use Web Workers With Ionic in One Go

Web Workers are very useful for handling heavy calculations. The code is working in a background thread and the UI can be used with no issue.
Web Workers are available in traditional JavaScript and that's what we are going to use in our Ionic mobile application.
We will create an application that will use one of the most famous algorithm: the QuickSort algorithm.

Let's create a new Ionic project:

ionic start ionic-webworkers blank

And update the home.html file:

<ion-header>
  <ion-navbar>
    <ion-title text-center>
      Ionic Web Worker
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  Result: {{result}}
</ion-content>

The result of the algorithm will be displayed there. If you are not familiar with this algorithm, it orders an array by swapping the numbers until it's properly ordered, here is an example:

Ionic Web Worker Quicksort-example

Moving on to the home.ts initialization:

import { Component, NgZone } from '@angular/core';
import { NavController } from 'ionic-angular';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
  result;

  constructor(public navCtrl: NavController, public ngZone: NgZone) {
  }
}

Two properties here:

  1. result: Where the result of the operation will be stocked
  2. ngZone: Angular tracks changes in the JavaScript files and update the properties in the templates. This is done by putting all of those methods, hooks, etc. in a zone that is watched. Web Workers aren't in this zone so everything related to a Web Worker won't be detected by Angular and our template won't change. In order to include some code into this zone, the NgZone Service will be used

Let's populate our constructor now:

  constructor(public navCtrl: NavController, public ngZone: NgZone) {
    const myWorker = new Worker('./assets/workers/worker.js');

    myWorker.onmessage = (event) => {
      this.ngZone.run(()=> {
        this.result = event.data.join(',');
      })
    };

    myWorker.postMessage('startQuickSort');
  }

A new Web Worker will be created by using the code located in assets/workers/worker.js.

The onmessage callback will be used to acquire the result of the Web Worker's process. As stated before, Angular's Zone doesn't watch what is happening here, we have to notify it by using the ngZone's run method.
The result property will be updated using the event.data property and joining the array's content to create a string.

Once the callback is prepared, we are ready to use the postMessage method to send a message to the Web Worker.

Moving to the web-worker.js file:

self.onmessage = function(event) {
  self.startQuickSort();
};

When a message is received, the startQuickSort custom method is triggered. We don't really care about the message however, the event parameter here is generally used to trigger different methods according to the message's type.

The startQuickSort method is as follow:

self.startQuickSort = function() {
  const LENGTH = 20;
  const MAX_VALUE = 2000;
  const arr = [...new Array(LENGTH)].map(() =>
    Math.round(Math.random() * MAX_VALUE)
  );

  const result = self.quickSort(arr, 0, arr.length - 1);

  self.postMessage(result);
};

A new array of random number is created. This is done by creating a new Array of 20 undefined values then using the map method to loop on each value, generate a random number and return a new array.

Once the unordered array is ready, a quickSort custom method is used to sort it.
Finally the Web Worker's postMessage method sends the result back to the callback located in the home.ts file.

Here is the whole quickSort algorithm:

self.swap = function(arr, i, j) {
  var temp = arr[i];
  arr[i] = arr[j];
  arr[j] = temp;
};

self.partition = function(arr, pivot, left, right) {
  var pivotValue = arr[pivot],
    partitionIndex = left;

  for (var i = left; i < right; i++) {
    if (arr[i] < pivotValue) {
      swap(arr, i, partitionIndex);
      partitionIndex++;
    }
  }
  swap(arr, right, partitionIndex);
  return partitionIndex;
};

self.quickSort = (arr, left, right) => {
  var len = arr.length,
    pivot,
    partitionIndex;

  if (left < right) {
    pivot = right;
    partitionIndex = partition(arr, pivot, left, right);

    //sort left and right
    quickSort(arr, left, partitionIndex - 1);
    quickSort(arr, partitionIndex + 1, right);
  }
  return arr;
};

Introduction to Ionic Google Analytics

The Ionic Build Process Tutorial

ES6 Features That Can't Be Ignored (part 1)

Stay up to date


Join over 4000 other developers who already receive my tutorials and their source code out of the oven + other free stuff!