DEV Community

Cover image for VueJS - Dedicated Web Worker Implementation
Pablo Veiga
Pablo Veiga

Posted on

VueJS - Dedicated Web Worker Implementation

JavaScript is a synchronous and single-threaded language and, because of it, it cannot take full advantage of multi-core CPUs.

Nevertheless, it provides some mechanisms that allow us to perform certain asynchronous operations and wait for their responses without blocking the main thread and, sometimes, the interface.

This article explains each one of these mechanisms.

Even though there are some ways to perform asynchronous operations in JavaScript, sometimes, they are not enough. Consider, for example, a big for loop where operations need to be performed following a certain order.

There is not a way for us to do that asynchronously or even taking advantage of the multiple cores of our CPU. Well, at least, there wasn't.

With HTML 5 and modern web APIs, we are now capable of executing code that demands heavy processing without blocking the main thread and, consequently, the interface.
Today, I am talking about one of them: the Web Workers.

The official specification mentions three types of workers:

Dedicated Workers are instantiated by the main process and can communicate only with it.

Shared Workers may be accessed by all processes executed in the same origin (different browser tabs, iframes or other shared workers)

Service Workers are event-oriented workers registered to an origin and a path. They are capable of controlling the website/page to which they are related, intercept and modify navigation and resource requests, and cache resources in a very granular way.

Source: https://thecodersblog.com/web-worker-and-implementation

In this post, I am going to talk about how to implement a Dedicated Worker in VueJS and use it to take advantage of multi-core CPUs.

There are some ways to implement Web Workers within a VueJS project:

It is pretty easy to implement a Dedicated Web Worker in a VueJS project.

Implementing a Dedicated Web Worker in VueJS

  1. Create a .js file in your public folder;

  2. Implement an onmessage function that receives an event as a parameter, process data* and, at the end of its execution, calls postMessage, passing the results as a parameter.

*The data passed as a parameter to this worker can be retrieved from event.data property.

  1. In a Vue Component, instantiate a new Worker and pass the absolute path of the recently created .js file as a parameter in its constructor.

  2. Implement the functions onmessage and onerror.
    They are callbacks executed when the messages are received from the Worker and in case of any error, respectively.

  3. Considering the problem you need to solve, create chunks from your data (you may use lodash/fp/chunk function) and iterate on them calling worker.postMessage passing the chunk as parameter.

The structure of both files will be similar to these:

// ./public/worker.js file

onmessage = function(event) {
  var data = event.data // data sent by the Vue component
is retrieved from 'data' attribute

  var result = doSomething()

  postMessage(result)
}

Enter fullscreen mode Exit fullscreen mode
// Worker.vue
import { chunk, map } from 'lodash/fp'

export default {
  props: ['data'],
  computed: {
    chunkedData() {
       const size = Math.ceil(this.data.length / 4) // In this case, 4 threads will be created
       return chunk(size, this.data)
    }
  },
  run() {
    const worker = new Worker('/worker.js')

    worker.onmessage = function(event) {
      const data = event.data // Data passed as parameter by the worker is retrieved from 'data' attribute
      console.log(data)
    }

  worker.onerror = console.error // This will be executed in case of any errors

   map(chunk => worker.postMessage(chunk), this.chunkedData)
  }
}
Enter fullscreen mode Exit fullscreen mode

Using this structure you will be able to instantiate a Web Worker, split the data into chunks and process each one of them asynchronously taking advantage of multiple threads and avoiding interface and browser freezing.

**Obs.: I strongly suggest using ES5 code inside the worker.js file. By the time this article is being written, ES6+ code within Web Workers is still not fully supported by all browsers.*

You can find a full example of this implementation in this repo.

Hope you liked it! Share and comment.

Cover image by @helloimnik

Top comments (1)

Collapse
 
sgkul2000 profile image
Shreesh Kulkarni

Hey, needed some help with shared web workers. ping me?