Async functions

The different shapes of async functions

Async arrow functions look like this
const foo = async () => {
  // do something
}
Async arrow functions look like this for a single argument passed to it
const foo = async (evt) => {
  // do something with evt
}
The anonymous form works as well
const foo = async function () {
  // do something
}
An async function declaration looks like this
async function foo() {
  // do something
}
Using async function in a callback
const foo = event.onCall(async () => {
  // do something
})
Native fetch in a one-liner
const getPost = async (id) => {
  return await (
    await fetch(`https://jsonplaceholder.typicode.com/posts/${id}}`)
  ).json()
}

However, it is difficult to properly error-handle it. You probably want to use this pattern instead.

fetch("anything")
    .then(response => {
      if(!response.ok) { // status not in the 200-range
        if(response.status === 404) throw new Error("Not found")
        else if(response.status === 401) throw new Error("Unauthorized")
        else if(response.status === 418) throw new Error("I'm a teapot !")
        else throw new Error("Other error")
      }
      else // ... could be [return response.json;] for example
    })
    .then(data => /* ... */)
    .catch(error => { /* network error / offline */ })

Since this quickly becomes quite verbose and non dynamic you might be intrested in extending the native error. Or use a library like Wretch.

So how to load in parallel with best practice in mind?

Key here is to use allSettled instead of Promise.all with a try/catch.

async function getPageData() {
  const result = await Promise.allSettled([fetchUser(), fetchProduct()])

  const [user, product] = handle(result) //case not result.ok===true, error handle to the best of your ability.
}

People interested in this article also found good use of this: