JavaScript Async - The Callback & The Controller
Written by Ian Ellliot   
Monday, 31 December 2018
Article Index
JavaScript Async - The Callback & The Controller
The Problem With Async
Using The Controller

For example if the non-blocking functions are:

function longRunA(callback) { 
console.log("A");
setTimeout(callback, 2000);
}
function longRunB(callback) {
console.log("B");
setTimeout(callback, 1000);
}

Then just calling the functions results in A being printed followed more or less immediately by B.

However, using:

controller.add(longRunA);
controller.add(longRunB);
controller.run();

Results in A being printed followed by B after 2 seconds. That is, longRunB only starts after longRunA ends.

This is simpler and arguably better than nested callbacks, but it has problems of its own. In particular, the functions that are in the queue have to have a known set of parameters so that they can be called correctly.

For example in this case each non-blocking function only accepts a callback. Also in this case the callback doesn't do any processing. All of these limitations can be overcome, but only at the cost of increased complexity.

You can also arrange for a controller object to call non-blocking functions a number of times or conditionally, so allowing you to implement the standard types of flow of control asynchronously. The problem is the same as for the simple sequential flow, however.

The controller object has to be crafted to suit your particular needs or it has to be complex to achieve a generality.

The common idea is that the callback passed to the non-blocking function is a method of the controller object which is used to perform the next action.

For example, to extend the controller so that it can repeat a non-blocking function a set number of times:

controller.count=0;
controller.current=0;
controller.repeat=function(n){
controller.count=n;
controller.current=controller.queue.shift();
controller.next();
};
controller.next=function(){
if(controller.count===0)return;
controller.count-=1;
controller.current(controller.next);
};

The repeat method gets the iteration started and the next method moves it on one and terminates it when the count has been exhausted. For example:

controller.add(longRunA);
controller.repeat(3);

repeats longRunA three times.

You can see how you could turn repeat into say a timeout with a retry function or test the return value for success or failure etc.

The controller method is particularly appropriate if what you are trying to do fits the finite state model. Then you can provide the controller with a state variable, call non-blocking functions, and change the state depending on the results as they happen.

However, this said, in most cases what you want to do is not regular enough for this approach and Promises or async/await are a better option.

Summary

 

  • To keep the UI active long running functions are non-blocking and return the UI thread before they have finished their work.

  • Non-blocking functions make use of callbacks or events to process the results of their work.

  • Callbacks are like event handlers, but they generally make use of the context they were called from.

  • Closure allows a callback to access its call context.

  • Asynchronous code distorts the flow of control – sequential execution becomes nested callbacks.

  • Asynchronous code makes error handling more difficult than it already is.

  • One way to implement the traditional flow of control using asynchronous functions is to implement a controller object which has methods that are used as callbacks.

  • Controllers work well if the situation can be implemented as a state machine.

 

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.

espbook

 

Comments




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

<ASIN:1871962560>

<ASIN:1871962579>

 <ASIN:1871962528>

<ASIN:1871962501>



Last Updated ( Monday, 31 December 2018 )