JavaScript Async - Basic Worker
Written by Ian Elliot   
Monday, 17 April 2023
Article Index
JavaScript Async - Basic Worker
The Trouble With Threads
Worker Thread To UI
The Event Problem

Until recently JavaScript has had no way to use any thread of execution other than the UI thread. For a language that was designed to work in an asynchronous event handling environment this is surprising. Today modern JavaScript does have additional threads and it is important to know how to use them.

This is an extract from my book JavaScript Async: Events Callbacks, Promises & Async/Await.

Now Available as a Book:

 JavaScript Async

cover

You can buy it from: Amazon

Contents

  1. Modern JavaScript (Book Only)
  2. Events,Standard & Custom
  3. The Callback
      extract - The Callback & The Controller
  4. Custom Async - setTimeout, sendMessage & yield
      extract - Custom Async
      extract - Avoiding State With Yield 
  5. Worker Threads
      extract - Basic Worker ***NEW
      extract - Advanced Worker Threads 
  6. Consuming Promises 
  7. Producing Promises
      extract - The Revealing Constructor Pattern
     
    extract - Returning Promises
     
    extract - Composing Promises
  8. The Dispatch Queue
      extract - Microtasks
  9. Async & Await
      extract -  Basic Async & Await
      extract -  DoEvents & Microtasks
  10. Fetch, Cache & Service Worker
      extract - Fetch  
      extract - Cache
     
    extract -  Service Workers

The sort of asynchronous function we constructed in the previous chapter is more like simulated async rather than the real thing. It is simply a way of breaking up the execution into small chunks that release the UI thread to handle events before starting on the next chunk. This is not how the system provided non-blocking functions do the job. They generally start another thread of execution to do their allotted task and free the UI thread only to use it again when the task is complete and the callback has to be run.

This is ok for many purposes, but the lack of the ability to directly use another thread of execution is a limitation on what you can do easily in JavaScript.

Thus most asynchronous programming that occurs in practice is where another thread of execution is used to complete a long running task while the UI thread gets on with what it is supposed to do i.e. look after the UI.

For example, when you start an AJAX file download the operating system allocates another thread to look after the task. From the point of view of a JavaScript programmer it all seems magical. You ask for a file and some time later the file is available and all without the UI thread having to do anything at all. This is usually how we view asynchronous code in JavaScript, but behind the scenes the OS is busy scheduling threads.

There is also the very real possibility that the hardware supports multiple cores and the other thread might well be really running in parallel with the UI thread. That is, the OS can implement true parallel execution and this makes things work faster.

Until recently there was no way that a JavaScript programmer could take advantage of the OS to schedule threads or of multiple cores to implement true parallelism, but now we have the Web Worker which implements background processing on a non-UI thread.

This is also the basis of the Service worker facility that is used in the construction of progressive web apps – which are likely to be the next big thing in web app design. The Service Worker is the subject of Chapter Ten.

First we need to recap the basic principles of using a Web Worker.

Basic Web Worker

The good news is that Web Worker is very easy to use.

What is slightly difficult to get to grips with is working out what you are not allowed to do and achieving simple communication between the threads.

Ideally you should wrap any Web Worker tasks you create as Promises to make the code easier to use. We will take a look at how to do this in Chapter Seven – for the moment let's concentrate on using Web Workers raw.

There really is only one key object when using Web Workers, the Worker object.

The Worker object automatically starts a new thread and begins executing JavaScript code as soon as it is created.

The basic action is that it loads the JavaScript file that you specify in its constructor and starts the script executing on a new thread. It is possible to avoid using a separate file to store the code, but it is messy and best avoided. The reason the code is in a separate file is to keep the execution contexts separated on the threads. That is, the program that starts on the new Worker thread has no shared variables with the code that creates it.

So for example, if you have a program stored in myScript.js the instruction to run it is:

var worker=new Worker("myScript.js");

Although this is simple there is a subtlety that you need to get clear if you are to avoid making silly mistakes.

When you create a Worker object two things happen.

  1. The code stored in myScript.js or whatever file you specify, is loaded and set running using a new OS level thread.

  2. A Worker object is created on the UI thread and this is an object that your "standard" JavaScript code running on the UI thread can use to communicate with the new Worker thread.

If you think that this is obvious and doesn't need to be said, so much the better.

workerthread1

In the example given above worker is an object that exists on the UI thread and "myScript.js" loaded and running in isolation from the UI thread and the program that worker belongs to. Of course the Worker object provides methods that allow communication between the two programs and this is something we have to find out how to use.

If you need to load a library into the Worker thread's code you can use the importScripts function. You simply supply the URLs of the scripts to load as parameters. The scripts are downloaded in any order, but executed in the order you specify. The importScripts function is synchronous and blocks until all of the libraries have been downloaded.

Notice that you can try and load standard libraries into a Worker thread, but as the DOM is unavailable they might not work. For example jQuery certainly doesn't work as it needs the DOM to function.



Last Updated ( Wednesday, 19 April 2023 )