Using Async/await in Javascript

These commands are the most recent evolution in Javascript asynchronous code execution syntax. They build on promises to improve the code syntax.

Why these constructs are so prominent in javascript

They come up a lot because JS does operations asynchronously whenever possible. In many languages, you expect when calling a function for the code to wait for the return. In javascript the assumption is opposite; if the operation can be asynchronous, don’t wait unless told to. While I almost never use them on the frontend for obvious reasons, they are frequently present in my node scripts. Examples of use include when I am writing to a database using streams and don’t want the write stream to get overwhelmed by the input thrown at it, as seen In my stream tutorial..

How using async/await works generally

await indicates to wait for the result of an asynchronous function, which is the same as waiting for a promise. Code after the await asyncFn() acts as if it was in a promise .then() block.

// If the operation is asynchronous, it fires off, the program continues
asyncFn()
otherfn()
// You can wait for it to finish however, if you need operations in sequence 
await asyncFn()
otherfn()

How to write async functions a few different ways

In order to be able to wait for a function conducting async operations, it has to be declared async, which essentially turns it into a promise by having it return a promise. Since I tend to use arrow functions, here are some different async function creation syntaxes in case something elsewhere in this tutorial looks unfamiliar.

function async doIt(arg){  
  // operations 
}

const doIt = async function(arg) {
  // operations
} 

const doIt = async (arg) => { 
  // operations
}   

async (arg) => arg+10

If you want to be able to await, the containing fcn must be async -

It will be immediately apparent because of the error, but you can’t do this. If you await within a function, you are automatically making it
async.

const fcn1 = () => {
   // Nope, containing fcn not async
   await somethingAsync()
}

This is also why async doesn’t work at top level
This is something you don’t want to do anyway, but you will see it is not allowed if you try it.

// Dont do it, can't do it outside a fcn anyway.  
let rslt = await fcnAsync()

How to think about structuring async operations

Anytime you await asyncfcn(), execution is blocked. This should not be done in locations that will block the main thread of execution, since that will bring the whole program to a halt.
It will block the program anywhere you use it, but if it is part of the program that has been called such that it is executing in the background and the operation within that must be in order, then it is entirely appropriate.

Use it in function calls the program can move along from

When you have async operations with a required sequence, try and put them together in functions that spin off those operations. By spin off, I mean that it will be called normally from the main thread so that it does not need to be waited for, but interally it will do things in the correct order.

In order to functions to await operations, they must be declared Async

const fcnasync1 = async () =>{  
  var blah = await returnsPromise(args)  
  var blah2 = await anotherPromise(args)  
  // other code
}
const fcnasync2 = async () =>{  
  var rslt = await returnsPromise(args)  
  // other code
}

Calling functions with a series of async operations
This will fire of the async functions an not wait for them. All the operations within those functions however will execute in order, with the function waiting for fn to finish when await is specified. This way the calling program continues execution but the operations within the function execute in the correct sequence.

fcnasync1()
fcnasync2()

Async functions return promises; they are promises -

You could take an async function and use .then() with it. async indicates to JS to transform the function into one that returns a promise and can also wait for asyc operations inside.
So don’t expect return value from async fcn
If a funciton is async, you can only get a return value from it if you are able to await the fcn’s return.

What makes async/await worth using over promises

Async/await is just a syntax wrapping around promises, but it is a very useful one.

Demonstration of this with a promise converted to async

The promise version requires code to be executed after a promise resolves to be nested in the .then() block.

PromiseFcn()  
  .then(response => {  
     // do stuff, then return another promise 
   }).then(response => {  
     // all code to be executed after second promise
   }).then(response => {  
     // code for after third promise.
   }).

The main shortcoming I see is needing to nest all the code in the .then() blocks, which gets awkward and strung out if you have several promise operations in a row and a bunch of operations to do in between.

The same thing with async/await

This code will operate the same way, but the syntax looks like any other JS code, and can be broken up into functions the same way. I think this is really flexible and useful.

const mainFcn = async () => {  
 let val1 = await promiseFcn()  
 let val2 = await promiseFcn2()  
 let val3 = await promiseFcn3()  
  // more operations  
  // don't return unless you expect to call with await. 
}

How to convert a callback into promise

If you find some library or code where you want to use promises/async/await nstead of callbacks, the conversion should be pretty simple. The process is to take the object that uses a callback, and wrap the use of that callback with a promise, with the reject/resolve used inside the callback to produce the results you want from the promise.

function connClient(url){  
  let client = new someObject(url)  
  return new Promise((resolve, reject) => {  
    client.connect((err, client) => {  
      if(err) reject(err);  
      else resolve(client);  
    })
  })
}

Then you can use it with async/await:

const useConverted = async (url) => {
  let connected = await connClient(url) 
  connected.doSomething() 
}

Summary

Async/await is a syntax layered on top of promises in JS. It takes a good idea in the form of promises and makes them easier to put into use. The two of them together represents a great improvement over callbacks, and with a small effort it is possible to convert callbacks into promises by just wrapping them.