JavaScript Async - Custom Async
Written by Ian Elliot   
Monday, 05 November 2018
Article Index
JavaScript Async - Custom Async
A Piece of Pi
Using a Callback

If you want to write JavaScript apps that are responsive, you have little choice but to master the art of creating your own non-blocking asynchronous functions. In this chapter extract we look at ways of working with the event queue to keep the UI working.

This is an extract from the recently published 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

To keep the UI responsive you have to let the UI thread do its job – which is to service the UI.

There are only two ways to do this:

  • you can opt to do your computation on the UI thread and arrange to release it frequently enough for it not to be missed

 or

  • you can use a separate thread of execution.

In many ways using a separate thread is the best possible solution and it is the subject of the next chapter. However, using worker threads has its drawbacks. The biggest is that it isn't supported on all browsers and when it is some features vary. It can be difficult to write a multi-threaded program that works on all modern browsers.

There is also the problem of passing data between the threads and updating the UI in particular. For many simple cases managing the UI thread to do the work is an attractive option and it is certainly worth knowing what techniques are available to you to do so.

Custom Non-Blocking Functions

JavaScript has a number of non-blocking functions, mostly to do with downloading files, and when you make use of them you have write asynchronous code. However, the story doesn't stop with supplied functions. If you have any difficult task to perform it has to be implemented as a non-blocking custom function.

Key to doing this in a way that will work on almost any browser and version of JavaScript is the setTimeout function that we met in chapter Two. This will place a message in the event queue that calls a function after a set time.

If you need a super efficient custom non-blocking function then you can use postMessage to add to the event queue without a minimum delay and this was also introduced in chapter Two.

But for simplicity let's start with setTimeout and return to postMessage later. We have already used them to implement true custom events, but their use in more general custom non-blocking functions is more important and worth going over again.

All you have to do is call setTimeout with a delay of zero:

setTimeout(function(){do something},0);

This effectively puts the function on the event queue and then returns immediately. Of course, the function will not be processed by the event queue until the UI thread is released.

A simple example should make this clear:

console.log("before");
setTimeout(function () {
  console.log("MyAsyncFunction");
}, 0);
console.log("after");

The sequence of events is that first "before" is sent to the log, then the function is added to the event queue with a timeout of 0, but the function cannot be called until the UI thread is freed. The setTimeout returns at once and "after" is sent to the log and the UI thread is freed, assuming this is the last JavaScript instruction. Only then does the function get to run and send "MyAsyncFunction" to the log.

You can see that the order of execution is not what you might expect, and this is typical asynchronous behavior. Notice also that the event queue is processed in whatever order the events occurred in, and if there is an event waiting to be processed it could be done before your custom function is called.

You can make use of this to break up a long running function so as to keep the UI responsive.

We have to arrange for the function to be "minimally" blocking by managing its use of the UI thread.

If you can't or don't want to use another thread then you have no choice but to divide up the calculation into small chunks. Each chunk should take a short enough time for the user not to notice that the UI isn't being serviced. The function has to restart after the break and it has to continue from where it left off. Notice that this introduces a new consideration into the mix and this is not just a matter of implementing a callback to use an existing non-blocking function, nor is it as simple as implementing a custom async event.

The general idea is very simple, but the details vary according to the algorithm.

coverasync

 

<ASIN:1871962560>

<ASIN:1871962579>



Last Updated ( Saturday, 10 November 2018 )