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

Periodic Updates – The Event Problem

There is nothing stopping you from adding a periodic update to the Worker thread so that the UI thread displays the progress of the calculation. You might think that all you have to do is setup a periodic event using setTimeout or setInterval something like:

var state = {};
state.k = 0;
state.pi = 0;
var i;
setInterval(this.postMessage(state),1000);
for (i = 0; i < 100000000; i++) {
    state.k++;
    state.pi += 4 * Math.pow(-1, state.k + 1) /
(2 * state.k - 1);
}
this.postMessage(state);

Notice that the setInterval fires an event every 1000 ms i.e. every second that the UI will process and display the status. If you try it you will discover that it doesn't work. The reason is very obvious once you notice that the Worker thread is fully occupied when the one second events occur and so they remain in the worker's event queue. Notice that it is the Worker thread that processes the worker's event queue. The periodic updates occur all at once when the calculation is over and continue to happen from then on.

If the Worker thread is occupied with a computation then it can't service the event queue.

This is exactly the same problem we had with the event-driven UI thread and it is the problem with all event-driven threads – they have to be doing nothing to respond to events.

We could use the techniques we used to break up the calculation in the UI thread, but this would lose us some of the advantage of using a Worker thread. You might think that the solution is to use yet another Worker thread just to service the regular events, but the problem here is that another Worker thread would not have access to the status object.

The simplest solution is to include a timer in the loop that does the calculation and use it to fire the message event:

var state = {};
state.k = 0;
state.pi = 0;
var i;
var time=Date.now();
for (i = 0; i < 100000000; i++) {
    if(Date.now()-time>1000){
        this.postMessage(state);
        time=Date.now();
    }
    state.k++;
    state.pi += 4 * Math.pow(-1, state.k + 1) /
(2 * state.k - 1);
}
this.postMessage(state);

This works, but testing the time every iteration is inefficient. However, attempts to make it more efficient are not easy.

In chapter but not in this extract

  • Controlling The Worker
  • The Async Worker Thread
  • Running a Worker Without a Separate File
  • Transferable Objects
  • Shared and Service Workers

Summary

  • You can create a Worker object which runs on a different thread to the UI thread.

  • The UI thread doesn't share any objects with the new thread and vice versa.

  • The Worker thread has access to all of JavaScript and a subset of the global objects available to the UI thread.

  • Communication from the thread that created the Worker object to the new thread makes use of its postMessage method.

  • Communication from the Worker thread to the thread that created it also makes use of the postMesssage method, but of the DedicatedWorkerGlobalScope object.

  • In each case a message event is triggered on the appropriate thread and the data property of the event object provides the data sent as part of the message.

  • The data transferred to the worker thread and to the UI thread is a copy, a clone, of the original.

  • By limiting the way the thread can interact, the JavaScript programmer is protected from the main difficulties of multi-threading and we don't have to worry about locks and race conditions.

  • A big problem with using Worker threads is that communication is event driven, but the Worker thread is at its most simple when just ignoring asynchronous considerations and just gets on with the job.

  • To allow for responsive communication between the threads both have to be written in an asynchronous style. Any long running function in the Worker thread will mean that it doesn't respond to messages sent to it from the UI thread.

  • You can use a Blob object and a Data URL to avoid having to use a separate file for the Worker's code.

  • A faster way to exchange data between threads is to use transferable objects.

  • As well as dedicated Workers you can also create SharedWorkers which can pass messages between different threads and ServiceWorkers which make implementing web apps easier. Neither are supported by Safari.

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

Also by Ian Elliot

Just JavaScript: An Idiomatic Approach
Just jQuery: The Core UI 
Just jQuery: Events, Async & AJAX

To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin.

C book

 

Comments




or email your comment to: comments@i-programmer.info

<ASIN:1871962560>

<ASIN:1871962579>

 <ASIN:1871962528>

<ASIN:1871962501>



Last Updated ( Wednesday, 19 April 2023 )