DEV Community

Juan Cruz Martinez
Juan Cruz Martinez

Posted on • Originally published at livecodestream.dev on

Most Common Ways to Make HTTP Requests in JavaScript

Live Code Stream - Programming | Career | Freelancing

In modern web development, one of the most important aspects is the ability to communicate with servers and other resources to fetch or send data. HTTP (Hypertext Transfer Protocol) is the foundation of data communication on the World Wide Web, and it allows clients (such as web browsers) to request and receive data from servers. As a web developer, understanding how to make HTTP requests is essential for creating dynamic and interactive web applications.

JavaScript, the most widely used programming language for client-side web development, provides several ways to make HTTP requests. These methods enable web applications to interact with servers, APIs, and other resources, facilitating the exchange of data in various formats, such as JSON, XML, or plain text.

In this article, we will explore the most common ways to make HTTP requests in JavaScript, including XMLHttpRequest, Fetch API, Axios, and jQuery Ajax. We will discuss their usage, syntax, and advantages, as well as potential limitations and browser support. This knowledge will help you choose the most suitable method for your projects and expand your skillset as a web developer.

Let’s get started!

Useful tutorials, guides, and career tips for developers, delivered once a week.

Subscribe and get a FREE copy of my book ten learning strategies.















    Sending...


    DOWNLOAD THE FREE EBOOK






    Fetch API

    The Fetch API is a modern and powerful alternative to XMLHttpRequest for making HTTP requests in JavaScript. Introduced as a native feature in modern browsers, the Fetch API is designed to be more concise, readable, and easier to use than its predecessor. It is built on top of the Promises API, which simplifies the process of handling asynchronous operations and managing complex workflows.

    One of the key advantages of the Fetch API is its native support for making requests outside the same-origin policy using CORS (Cross-Origin Resource Sharing). This enables web applications to interact with resources hosted on different domains more easily and securely.

    Following a promise-based syntax, we can use Fetch to send HTTP requests from the client-side, as this example shows.

    fetch("https://world.openfoodfacts.org/category/pastas/1.json")
      .then(response => {
        // indicates whether the response is successful (status code 200-299) or not
        if (!response.ok) {
          throw new Error(`Request failed with status ${reponse.status}`)
        }
        return response.json()
      })
      .then(data => {
        console.log(data.count)
        console.log(data.products)
      })
      .catch(error => console.log(error))
    
    
    Enter fullscreen mode Exit fullscreen mode

    Fetch significantly reduces the complexity and verboseness of the code with the use of simpler syntax and promises. In this implementation, we have to use the response.ok field to check whether the response contains an HTTP error or not because the errors caught in the catch method belong to the network level, not the application level.

    The fetch method accepts a configuration object as the second parameter to allow easy manipulation of HTTP fields like headers, content-types, the request method, etc. You can find the complete list of configuration options Fetch supports in its official documentation.

    Making POST requests with Fetch also follows a similar pattern to the previous example. Here, we use the config object to specify the request method and pass data that needs to be posted.

    Let’s try this implementation using async/await:

    async function postData () {
      const food = {
        name: "Bread",
        weight: 450,
        quantity: 3
      }
    
      const response = await fetch("/food", {
        method: "POST",
        body: JSON.stringify(food),
        headers: {
          "Content-Type": "application/json"
        }
      })
    
      if (!response.ok) {
        throw new Error(`Request failed with status ${reponse.status}`)
      }
      console.log("Request successful!")
    }
    
    
    Enter fullscreen mode Exit fullscreen mode

    Pros of Fetch API

    • Modern, concise, and more readable syntax based on Promises, making it easier to use and understand compared to XMLHttpRequest.
    • Native support for making requests outside the same-origin policy using CORS, which simplifies interactions with resources hosted on different domains.
    • Built-in error handling with the catch method, allowing for improved error handling capabilities in web applications.
    • Provides additional features over XMLHttpRequest such as integrating Request and Response objects with the native Cache API and sending no-cors requests.
    • Natively supported in modern browsers, eliminating the need for additional libraries.

    Cons of Fetch API

    • Lacks some useful features supported by XMLHttpRequest such as aborting a request and monitoring request progress. (However, it allows the use of a separate AbortController object to control request aborts and timeouts.)
    • Accepts a response even when an HTTP error occurs. We have to manually check for HTTP errors and handle them.
    • No built-in progress monitoring for requests, which can be useful for tracking the progress of large file uploads or downloads.

    Axios

    Axios is a popular and widely used JavaScript library for making HTTP requests. It offers a simple, clean, and easy-to-use API based on Promises, making it an attractive choice for developers who prefer a more readable and concise syntax compared to XMLHttpRequest. Unlike the Fetch API, Axios works seamlessly in both browser and Node.js environments, making it a versatile solution for various types of projects.

    The library provides a range of advanced features and built-in functionality, such as error handling, request cancellation, and interceptors, which can be used to modify requests and responses globally or on a per-request basis. Additionally, Axios automatically transforms JSON data, simplifying the process of sending and receiving data in a common format.

    When making GET requests with Axios, we can use the dedicated axios.get() method to compile the request. Here we’ve shown an example of the implementation:

    axios.get("https://world.openfoodfacts.org/category/pastas/1.json")
      .then(response => {
        // access parsed JSON response data using response.data field
        data = response.data
        console.log(data.count)
        console.log(data.products)
      })
      .catch(error => {
        if (error.response) {
          //get HTTP error code
          console.log(error.reponse.status)
        } else {
          console.log(error.message)
        }
      })
    
    
    Enter fullscreen mode Exit fullscreen mode

    As this example shows, Axios reduces the amount of work we have to do on our end to make HTTP requests even compared to Fetch. It automatically parses the received JSON data, which we can access through response.data field. Axios also catches HTTP errors in its catch method, removing the need to specifically check for status code before processing the response. Inside the catch method, we can distinguish HTTP errors using an error.response check, which stores the HTTP error code.

    For sending POST requests with Axios, we use the dedicated axios.post() method as the following example, implemented using async/await, shows:

    async function postData () {
      const food = {
        name: "Bread",
        weight: 450,
        quantity: 3
      }
    
      try {
        const response = await axios.post("/food", food)
        console.log("Request successful!")
      } catch (error) {
        if (error.response) {
          console.log(error.reponse.status)
        } else {
          console.log(error.message)
        }
      }
    }
    
    
    Enter fullscreen mode Exit fullscreen mode

    Again, Axios simplifies this implementation by automatically converting Javascript objects to JSON without our interception. These Axios methods also accept a final parameter specifying HTTP configurations.

    Other than these basic features, Axios provides solutions for many unique use cases that we won’t discuss here. But if you want to dive deeper into working with Axios in Javascript as well as Node.js, you can follow this in-depth guide to Axios on our blog.

    Pros of Axios

    • Easy-to-use and concise syntax based on Promises, offering a more readable and intuitive experience compared to XMLHttpRequest.
    • Built-in support for error handling and request cancellation, which simplifies the process of managing complex requests and improving the user experience.
    • Supports both browser and Node.js environments, making it a versatile solution for various types of projects and platforms.
    • Provides useful features like interceptors for modifying requests and responses globally or on a per-request basis, and automatic JSON data transformation.
    • Rejects on HTTP errors by default, making error handling more intuitive than the Fetch API.

    Cons of Axios

    • Requires an additional library to be added to your project, which can increase the overall size of the application.

    XMLHttpRequest

    XMLHttpRequest is a native API in Javascriptthat has been around since the early 2000s. It was initially developed by Microsoft and later adopted by other browsers. Although the name suggests that it is specifically designed for XML data, XMLHttpRequest can be used to request and handle a variety of data formats, such as JSON, HTML, and plain text.

    Over the years, XMLHttpRequest has become a fundamental building block for making asynchronous HTTP requests in web applications. However, its usage has somewhat declined with the introduction of more modern and easier-to-use alternatives, such as the Fetch API.

    Here’s how we can send GET requests and asynchronously retrieve data from a remote API using XMLHttpRequest API:

    //create XMLHttpRequest object
    const xhr = new XMLHttpRequest()
    //open a get request with the remote server URL
    xhr.open("GET", "https://world.openfoodfacts.org/category/pastas/1.json")
    //send the Http request
    xhr.send()
    
    //EVENT HANDLERS
    
    //triggered when the response is completed
    xhr.onload = function() {
      if (xhr.status === 200) {
        //parse JSON datax`x
        data = JSON.parse(xhr.responseText)
        console.log(data.count)
        console.log(data.products)
      } else if (xhr.status === 404) {
        console.log("No records found")
      }
    }
    
    //triggered when a network-level error occurs with the request
    xhr.onerror = function() {
      console.log("Network error occurred")
    }
    
    //triggered periodically as the client receives data
    //used to monitor the progress of the request
    xhr.onprogress = function(e) {
      if (e.lengthComputable) {
        console.log(`${e.loaded} B of ${e.total} B loaded!`)
      } else {
        console.log(`${e.loaded} B loaded!`)
      }
    }
    
    
    Enter fullscreen mode Exit fullscreen mode

    As this example shows, the process of sending a GET request with XMLHttpRequest involves three steps:

    • Create XMLHttpRequest
    • Opening the HTTP request of the indented type
    • Sending the request

    Once the request is sent, we can use the event handlers provided by the XMLHttpObject to handle its response. Here, we have used two event handlers: onload, onerror, and onprogress. It’s important to note here that onerror method only handles network-level errors related to the request. To identify HTTP errors, we have to check the HTTP status code inside the onload method specifically.

    We can send POST requests with XMLHttpRequest following a similar pattern.

    // create XMLHttpRequest object
    const xhr = new XMLHttpRequest()
    // open a POST request
    xhr.open("POST", "/food")
    // set content-type header to JSON
    xhr.setRequestHeader("Content-Type", "application/json");
    // send JSON data to the remote server
    xhr.send(JSON.stringify(food))
    
    // Event Handlers
    
    // track data upload progress
    xhr.upload.onprogress = function(e) {
      console.log(`${e.loaded}B of ${e.total}B uploaded!`)
    }
    
    // triggered when data upload is finished
    xhr.upload.onload = function(e) {
      console.log("Upload completed")
    }
    
    // triggered when the response is fully received
    xhr.onload = function() {
      console.log(xhr.status)
    }
    
    // triggered due to a network-level error
    xhr.onerror = function() {
      console.log("Network error occurred")
    }
    
    
    Enter fullscreen mode Exit fullscreen mode

    One main difference between the earlier GET and the current POST request is explicitly setting the content-type headers when posting JSON data. Also, there is an additional event type a POST request can trigger compared to a GET request. They are upload events accessed through the xhr.upload field. These event handlers help us track the data upload progress when the request body has to carry a significant amount of data (e.g., images, files, etc.)

    Pros of XMLHttpRequest

    • Excellent browser support, including older browsers like Internet Explorer 7 and above.
    • Removes the need for external dependencies.
    • Ability to monitor the progress of a request using the readystatechange event.

    Cons of XMLHttpRequest

    • Verbose and less intuitive syntax compared to modern alternatives.
    • No support for async/await or promise-based syntax.
    • Lacks some advanced features and error handling capabilities found in newer APIs.

    JQuery Ajax

    jQuery is a widely used and popular JavaScript library that simplifies various aspects of web development, such as DOM manipulation, event handling, and animation. One of its powerful features is jQuery Ajax, which provides a simple and easy-to-use API for making asynchronous HTTP requests. jQuery Ajax has been a popular choice among web developers for many years due to its simplified syntax and ease of use compared to XMLHttpRequest.

    The jQuery Ajax API offers several advanced features and options, such as error handling, timeout settings, caching, and support for JSONP (JSON with Padding) to work around cross-domain request limitations. These features make it an attractive option for developers who are already using jQuery in their projects or prefer a more simplified approach to making HTTP requests.

    Though it is from the pre-framework (like React, angular, etc) era, it is still adopted by many websites, specially when working with platforms such as wordpress and templates.

    Let’s see an example of a GET request with jQuery:

    $.ajax({
      url: 'https://world.openfoodfacts.org/category/pastas/1.json',
      method: 'GET',
      dataType: 'json',
      success: function(data) {
        // Handle the received data
        console.log(data);
      },
      error: function(xhr, status, error) {
        // Handle any errors
        console.error('Error: ' + status + ' - ' + error);
      }
    });
    
    
    Enter fullscreen mode Exit fullscreen mode

    Similarly, you can have a post request:

    $.ajax({
      url: 'https://world.openfoodfacts.org/category/pastas/1.json',
      method: 'POST',
      dataType: 'json',
      data: json,
      success: function(data) {
        // Handle the received data
        console.log(data);
      },
      error: function(xhr, status, error) {
        // Handle any errors
        console.error('Error: ' + status + ' - ' + error);
      }
    });
    
    
    Enter fullscreen mode Exit fullscreen mode

    Pros of jQuery Ajax

    • Simplified syntax and ease of use, making it more accessible for developers compared to XMLHttpRequest.
    • Provides advanced features and options like error handling, timeout settings, caching, and JSONP support for cross-domain requests, which can improve the overall user experience.
    • Widely adopted and popular due to the extensive use of the jQuery library in the web development community, ensuring a wealth of resources and support.

    Cons of jQuery Ajax

    • Requires the inclusion of the jQuery library, which may not be needed for other parts of the project, adding extra weight and complexity to the application.
    • Less relevant and less frequently used in modern web development due to the rise of alternative libraries and native APIs like Fetch and Axios, which offer similar functionality without the need for jQuery.
    • Not as lightweight and performant as native APIs like Fetch or XMLHttpRequest, which might be a concern for performance-sensitive projects or applications targeting slow connections or limited resources.

    Ky

    Ky is a relatively new Javascript package that can be used for making asynchronous HTTP requests from the front end of a web application. It’s built on top of the native Fetch API with a simpler syntax and additional functionality.

    Ky provides a simple syntax for making requests with its dedicated HTTP methods. Here’s an example of sending a GET request using Ky with async/await.

    async function getData () {
      try {
        const data = await ky.get("https://world.openfoodfacts.org/category/pastas/1.json").json()
        console.log(data.count)
        console.log(data.products)
      } catch (error) {
        if (error.response) {
          console.log(error.response.status)
        } else {
          console.log(error.message)
        }
      }
    }
    
    
    Enter fullscreen mode Exit fullscreen mode

    We can send POST requests following a similar pattern:

    async function postData () {
      try {
        const response = await ky.post("/food", { json: food })
        console.log("Request successful!")
      } catch (error) {
        if (error.response) {
          console.log(error.reponse.status)
        } else {
          console.log(error.message)
        }
      }
    }
    
    
    Enter fullscreen mode Exit fullscreen mode

    Pros of Ky

    • Gives a simple, lightweight, promise-based API for making HTTP requests.
    • Addresses some limitations in the native Fetch API with support for features like request timeout, retry, and monitoring progress.
    • Provides hooks for modifying requests during their lifecycle: beforeRequest, afterResponse, beforeRetry, etc.
    • Supports all modern browsers like Chrome, Firefox, Safari. For Internet Explorer support, Ky provides an alternative package, Ky-Universal, not sure why they still bother.

    Cons of Ky

    • Relatively a new package compared to other mature, versatile options discussed in this post. Adds an external dependency.

    Conclusion

    n conclusion, there are several methods available for making HTTP requests in JavaScript, each with its own advantages and disadvantages. Choosing the right method for your project depends on various factors, such as browser support, ease of use, performance, and the specific requirements of your application.

    In this article we explored, XMLHttpRequest, Axios, Fetch API, jQuery Ajax, and Ky with examples, pros and cons. By now you should be able to evaluate the specific needs of your project, and choose the most suitable approach for making HTTP requests in JavaScript, ensuring efficient and responsive web applications with improved error handling and versatile functionality.

    Note: Nowadays I almost always go with Axios or FetchAPI

    Thanks for reading!

    Newsletter

    Subscribe to my weekly newsletter for developers and builders and get a weekly email with relevant content.

    Top comments (0)