Skip to content
Tong Lam edited this page Mar 25, 2024 · 1 revision

How to use

# GET

import { getFetch } from "../../../static/js/fetch.js";

getFetch({url})({data})({header})
# POST

import { postFetch } from "../../../static/js/fetch.js";

postFetch({url})({data})({header})

All you need to remember is: getFetch(url)(data)(header) or postFetch(url)(data)(header).

If you don't need to use data or headers, just use empty parentheses.

Overall

In our project, we aim to streamline the process of making HTTP requests in frontend development by providing a simplified wrapper around the fetch API in JavaScript. This wrapper abstracts away the complexities of the fetch API and provides an easy-to-use interface for fetching data from APIs.

The encapsulation of the Fetch API into higher-order functions and currying demonstrates functional programming concepts. Explanations are provided below for those interested, or you can jump straight to the Usage section.

  • High order function: Higher-order functions are functions that can accept other functions as arguments or return functions as results. In our encapsulation, getFetch and postFetch are higher-order functions. They return another function that can be called with additional parameters to make the actual HTTP request. This allows for greater flexibility and reusability.

  • Currying: Currying is a technique in functional programming where a function with multiple arguments is broken down into a series of functions, each taking a single argument. This allows for partial application of arguments, where some arguments are provided initially, and the remaining arguments can be provided later. In our implementation, getFetch and postFetch are curried functions. They take the URL as the first argument and return another function that takes data and headers as subsequent arguments.

See: /app/static/js/fetch.js

Usage

Take an endpoint in our project as an example: /api/v1/auth/email_exists.

GET without data and customer headers

getFetch("/api/v1/auth/email_exists")()().then((res) =>
    console.log("GET response:", res)
  );

GET with data and without customer headers

getFetch("/api/v1/auth/email_exists")({email: "test@gmail.com"})().then((res) =>
    console.log("GET response:", res)
  );

GET with data and customer headers

getFetch("/api/v1/auth/email_exists")({email: "test@gmail.com"})({"X-Custom-Header": "test"}).then((res) =>
    console.log("GET response:", res)
  );

POST without customer headers

postFetch("/api/v1/auth/email_exists")({email: "test@gmail.com"})().then((res) =>
    console.log("GET response:", res)
  );

POST with customer headers

postFetch("/api/v1/auth/email_exists")({email: "test@gmail.com"})({"X-Custom-Header": "test"}).then((res) =>
    console.log("GET response:", res)
  );

Code

const fetchData = async (url, options = {}) => {
  try {
    const response = await fetch(url, options);
    if (!response.ok) {
      console.error(`HTTP error! Status: ${response.status}`);
    }
    const contentType = response.headers.get("Content-Type");
    if (contentType && contentType.includes("application/json")) {
      return await response.json();
    } else {
      return await response.text();
    }
  } catch (error) {
    console.error("Error:", error);
  }
};
const getFetch =
  (url) =>
  (data = {}) =>
  async (headers = {}) => {
    const queryParams = new URLSearchParams(data).toString();
    const apiUrl = queryParams ? `${url}?${queryParams}` : url;
    return await fetchData(apiUrl, { headers });
  };
const postFetch =
  (url) =>
  (data = {}) =>
  async (headers = {}) => {
    let options = {};

    if (data instanceof FormData) {
      options = {
        method: "POST",
        body: data,
        headers: headers,
      };
    } else {
      options = {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          ...headers,
        },
        body: JSON.stringify(data),
      };
    }

    return await fetchData(url, options);
  };

Clone this wiki locally