How do you make synchronous HTTP request in JavaScript?

In the current digital terrain, the act of making HTTP requests is a vital component in transmitting and receiving data between the client and server. Asynchronous requests have gained prevalence as they provide a non-blocking experience, which ultimately enhances the overall user experience. Nevertheless, there are certain situations where synchronous HTTP requests may prove necessary or preferable. In the ensuing narrative, we shall delve into the algorithm for creating synchronous HTTP requests using JavaScript. We will also explore two distinct approaches with their corresponding code explanations and practical applications.

Algorithm

To initiate synchronous HTTP requests in JavaScript, one must execute a basic algorithm that comprises of the subsequent phases −

  • Firstly, spawn an example of the HTTP request object.
  • Secondly, adjust the request by stipulating the methodology, uniform resource locator (URL), and enabling the request to synchronize mode.
  • Thirdly, dispatch the request.
  • Fourthly, await the response.
  • Lastly, handle the response accordingly.

Approaches

Using XMLHttpRequest

The XMLHttpRequest is a pre-existing object in JavaScript that has been in use for a considerable duration. Despite its substitution by contemporary alternatives, it still functions adeptly for executing synchronous HTTP requests. Below is an illustration of how to implement XMLHttpRequest −

function synchronousRequest(url) {
   const xhr = new XMLHttpRequest();
   xhr.open('GET', url, false);
   xhr.send(null);
   if (xhr.status === 200) {
      return xhr.responseText;
   } else {
      throw new Error('Request failed: ' + xhr.statusText);
   }
}

Example

Using the synchronousRequest function defined earlier −

try {
   const url = 'https://api.example.com/data';
   const responseData = synchronousRequest(url);
   console.log('Response data:', responseData);
} catch (error) {
   console.error('Error:', error.message);
}

Using Fetch API

The Fetch API is a modern alternative to XMLHttpRequest and is designed to be more flexible and easier to use. Unfortunately, the native fetch() function does not support synchronous requests. However, you can use async/await to create a synchronous-like behavior −

async function synchronousFetch(url) {
   const response = await fetch(url);
   if (response.ok) {
      const data = await response.text();
      return data;
   } else {
      throw new Error('Request failed: ' + response.statusText);
   }
}

Example

Using the synchronousFetch function defined earlier −

import React, { useEffect, useState } from "react";
import "./styles.css";
export default function App() {
   const [responseData, setResponseData] = useState(null);
   useEffect(() => {
      (async () => {
         try {
            const url = "https://jsonplaceholder.typicode.com/todos/1";
            const response = await fetch(url);
            if (!response.ok) {
               throw new Error(`HTTP error! Status: ${response.status}`);
            }
            const data = await response.json();
            setResponseData(data);
         } catch (error) {
            console.error("Error:", error.message);
         }
      })();
   }, []);
   return (
      <div className="App">
         <h1>API Data</h1>
         {responseData ? (
            <pre>{JSON.stringify(responseData, null, 2)}</pre>
         ) : (
            <p>Loading...</p>
         )}
      </div>
   );
}

Output

API Data
{
   "userId": 1,
   "id": 1,
   "title": "delectus aut autem",
   "completed": false
}

Conclusion

While asynchronous requests are generally preferred for their non-blocking nature, synchronous HTTP requests in JavaScript still have their use cases. We’ve discussed the algorithm for making synchronous HTTP requests and explored two different approaches, including the older XMLHttpRequest method and the more modern Fetch API with async/await.