Async/await AND Promises

We can all agree the only use left for callbacks in asynchronous programming in JavaScript is to know when an open source repository is not being maintained. Now async/await is here and the waters have been divided once again.

const getPosts = async () => {
  let response = await fetch('posts.json');
  console.log(response.status);
  return await response.json();
}
const getPosts = () => fetch('posts.json').then(response => {
  console.log(response.status);
  return response.json();
});

I don’t see many differences, but I am used to work with Promises, that may not be the case for many other programmers that come from other languages and might be annoyed enough because JavaScript took over the world and they just have to learn it. Some may not be familiar with asynchronous programming at all, and we want to make things easier for everybody don’t we? async/await helps to make Promises synchronous friendly. Others like those coming from C#, who are plotting the TypeScript coup, will be already familiar with the async/await notation.

public async Task<int> SumAsync(int x, int y) {
  await Task.Run(() => Console.Write("Dummy async operation"));
  return x + y;
}

But don’t rush your decision yet! Does this look acceptable to you?

var tmpSum = await SumAsync(1, 
  await SumAsync(1, 1)
);
Console.Write(tmpSum);
return await SumAsync(1,
  await SumAsyncForm(4,
    await SumAsync(5, tmpSum)
  )
);

The then method of Promises is really nice! C# is typed, so you will have to make many implementations of the same concept.

public static async Task<TOut> Then<TIn, TOut>(this Task<TIn> promise, Func<TIn, Task<TOut>> f) {
  return await f(await promise);
}
public static async Task<TOut> ThenSync<TIn, TOut>(this Task<TIn> promise, Func<TIn, TOut> f) {
  return f(await promise);
}

await SumAsync(1, 1)
  .Then(x => SumAsync(x , 1))
  .ThenSync(x => {
    Console.Write(x); 
    return x;
  })
  .Then(x => SumAsync(x , 5))
  .Then(x => SumAsync(x , 4))
  .Then(x => SumAsync(x , 1));

The Promise way in JS

sumAsync(1, 1)
  .then(x => sumAsync(x , 1))
  .then(x => {
    console.log(x);
    return x;
  })
  .then(x => sumAsync(x , 5))
  .then(x => sumAsync(x , 4))
  .then(x => sumAsync(x , 1));

Using then instead of async/await for composition nightmares also applies to JavaScript, of course, the syntax is exactly the same. Don’t toss Promises out, their functional implementation is a very nice pattern to have.

Async/await should not be seen as a way out of asynchronous programming, you cannot escape, it is good for the CPU and good for your user’s experience, embrace it.

Neither should it be seen as syntactic sugar for those that don’t understand Promises, it has objective advantages, like the ability to catch both asynchronous and synchronous code at the same time.

function thatMightFail() {
  function error(e) {
    console.log(e);
  }

  try { faultyFunc(); } catch (e) { error(e); }

  return fetch('something.json')
    .then(something => something.json())
    .catch(error);
}
function async thatMightFail() {
  try {
    faultyFunc();
    return await fetch('something.json')
      .then(something => something.json());
  } catch (e) {
    console.log(e);
  }
}
Advertisement