Defining API functions

Abstracting server communication in frontend applications

When I'm developing a web application I prefer to abstract the server communication logic into asynchronous functions.

Usually I would have an api.(js|ts) module where I would have a function for each endpoint.

For example if I want to make a GET request to /user/:id, i would define the following function:

// api.ts

export async function getUser(id: string) {
  const response = await fetch(`/user/${id}`);
  if(response.ok){
    return response.json() as Promise<User>
    // This way I can provide the type for the data I'm fetching
  } else {
    throw new Error("Something went wrong!")
    // I can also handle server errors
  }
}

One of the benefits is that now my Ui code does not know about requests and responses. This makes testing the code much easier.