Managing Asynchronous Code - Callbacks, Promises & Async/Await
Written by Mike James   
Monday, 21 March 2022
Article Index
Managing Asynchronous Code - Callbacks, Promises & Async/Await
The Callback And The Closure
onFulfilled and onRejected
Async and Await

The Ghost Of Promises Gone

After you have been using promises for a while it all gets to be second nature and you almost start to think that you are programming synchronous code but in a very strange way.

The reason is that it is easy to forget that the functions in the then methods are not obeyed immediately as part of the flow of control of your code. To avoid subtle mistakes you need to keep in mind that the Promise objects are created by the asynchronous methods you are using and they exist and are used long after your code has handed control back to the dispatcher. 

Overall promises are a step in the right direction but a fairly small one. 

The next approach takes the whole asynchronous problem and does its best to make it go away. 

Async and Await

Async and await are the simplest solution to the single threaded UI asynchronous problem for the user but the most difficult for the language creator to implement.

Currently it is only available in a small number of languages and it was introduced first into C# and there is a good chance it will be in the next version of JavaScript. It is also possible to add async and await to ECMAScript 2015 with a polyfill based on using yield. 

Async and await make the compiler do all the work - no callbacks and no need for promises. Essentially asynchronous code vanishes and you really don't need to know about it in any great detail. 

The basic idea is that any function that is marked as async can make use of await to give up the UI thread while an asynchronous operation completes. When it does complete the function resumes from where it left off with complete restoration of state.

Even though it is asynchronous it is coded exactly like a synchronous function. 

For example

async function(){
 var text=await LoadA();
   .. make use of text
 return result;

What happens is that when the LoadA function is called the UI thread is released and it gets on with servicing the UI and making the app look active. When LoadA finally completes the UI thread automatically returns to the await restores the state of the function, stores the result of the function in text and then gets on with the rest of the function as if nothing had happened. 

A typical async function can make use of multiple awaits and these can be within control structures. 

For example:

async function(){
 for(var i=0,i<10,i++){
  text(i)=await LoadA();

The point is that using async and await the problem of writing asynchronous code vanished - well almost. 

There are still many restrictions and "interesting" behaviours because you are using asynchronous code. Many of these problems are similar to the sort of things encountered when using "doEvents". For example the UI thread can respond to an event a second time and start the async function will it is still in the middle of an await. 

You might at this point be thinking why did we bother with promises?

A good question. The C# implementation of async and await makes use of Tasks and the JavaScript implementation makes use of the Promise class. You could say that async and await are built on top of promises and yield which is how they are polyfilled in ECMAScript 2015. At the moment a lot of the documentation and articles focus on how async and await are implemented and this makes at all seems complicated.  However is likely that in the future the average programmer will tend to forget the foundations and concentrate on the simplicity of async and await.

The point is that the sort of asynchronous code we are forced to write, at least on the client side, is due to the single threading of the UI. This is not something that is intrinsic to the programs we write and if the UI was multi-threaded we would simply wait for a long running operation to complete. In this sense the whole asynchronous problem is just a compiler problem. It is up to the compiler to make asynchronous operation look like synchronous operation and so hide the details from us. 

Asynchronous programming as implemented to cope with a single threaded UI isn't a solved problem but async and await gets are close as it is likely to get. 

The key idea is that single threaded UI asynchronous programming is a problem for the compiler not the programmer. 

Almost true.  


More Information


Async Functions specification 

async (C# Reference)

Mike James, Founder and Chief Editor of I Programmer is also a prolific author. In addition to his books on specific languages, Programmer's Python: Everything is an ObjectDeep C#: Dive Into Modern C#JavaScript Jems: The Amazing Parts and Programmer’s Guide To Kotlin, 2nd Ed, he has written The Programmer’s Guide To Theory which sets out to present the fundamental ideas of computer science in an informal, and yet informative, way. His latest book is The Trick Of The Mind: Programming and Computational Thought, aimed at programmers and non-programmers alike, which examines the nature of programming and reveals why it is a very special skill.

Related Articles

Task.js Asynchronous Tasks In JavaScript      

jQuery, Promises & Deferred

jQuery Promises, Deferred & WebWorkers

Why await? Why not multithread the UI?       

Async, Await and the UI problem       

What Is Asynchronous Programming?

Task.js Asynchronous Tasks In JavaScript

JavaScript Web Workers

Chaining - Fluent Interfaces In JavaScript

Being threadsafe - an introduction to the pitfalls of parallelism

The Perils of the C# Parallel For 

Async, Await and the UI problem

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.

kotlin book



or email your comment to:




Last Updated ( Wednesday, 23 March 2022 )