Graham King

Solvitas perambulum

Javascript’s async/await and Promise in a few words

This is a very common pattern in Javascript:

myFunc(value, successCallback, errorCallback)

If myFunc could block (such as on network access), we don’t want to block Javascript’s single thread, so we asked to be notified when the operation is complete.

Javascript added syntactic sugar to make this pattern more pleasant, in two steps.

The first step is adding a Promise object. myFunc would now returns a Promise, and the caller looks like this:

myFunc(value).then(successCallback, errorCallback)

Very similar. An improvement is you can now return this Promise up the call chain, instead of passing down your callbacks, and you can chain them. I sometimes think of Promise as ‘CallbackManager’. It wraps them and gives them a nicer interface.

The second step, and the key one, is the two new keywords async and await, that allow you to do this:

async function wrapper() {
  await myFunc(value);
  successCallback();
}

If a function returns a Promise, we can put await in front and pretend that in the success case our code is linear. It reads a lot better. The failure case throws an exception:

async function wrapper() {
  try {
    await myFunc(value);
    successCallback();
  } catch (e) {
    errorCallback();
  }
}

The async keyword, as far as I can tell, is just a marker for the Javascript interpreter to watch out for some voodoo within.

The function just looks linear. It executes like a callback, in that other code will run while myFunc blocks.

Let’s un-sugar an example, working backwards:

async function wrapper() {
  // code before
  try {
    await myFunc(value);
    // code after
  } catch (e) {
    // err case which you always
    // handle because you are a professional
  }
}

Is equivalent to:

function wrapper() {
  // code before
  myFunc(value).then(
    function(){ // code after },
    function(){ // err case }
  );
}

which is the modern way of writing:

function wrapper() {
  // code before
  myfunc(value,
    function(){ // code after },
    function(){ // err case }
  );
}

await offers a straightforward solution to Javascript’s callback-hell by making code significantly easier to read. Just remember to catch the exception.