Drani Academy – Interview Question, Search Job, Tuitorials, Cheat Sheet, Project, eBook

JavaScript

Tutorials – JavaScript


Chapter 14 – 
AJAX and HTTP Requests

 

In this chapter, we will explore the world of AJAX (Asynchronous JavaScript and XML) and HTTP requests in JavaScript. Understanding how to make asynchronous network requests is crucial for building modern web applications, where data retrieval and manipulation happen without requiring full page reloads. We will cover the basics of AJAX, various methods for making HTTP requests, handling responses, and working with popular data formats like JSON.

Introduction to AJAX

AJAX is a set of web development techniques that enable web applications to communicate with a web server asynchronously. It allows you to update parts of a web page without having to reload the entire page. AJAX is often used to retrieve data from a server, send data to a server, or update a web page dynamically.

The term “AJAX” originally stood for “Asynchronous JavaScript and XML.” While XML was commonly used as the data format in the early days of AJAX, modern applications often use JSON (JavaScript Object Notation) due to its simplicity and efficiency.

AJAX enables the development of responsive and interactive web applications, providing a smoother user experience. Instead of waiting for a full page reload, users can see changes happen in real-time.

Making Asynchronous Requests with XMLHttpRequest

The XMLHttpRequest object is a fundamental way to make asynchronous HTTP requests in JavaScript. It provides a straightforward approach to sending and receiving data from a web server without requiring a page reload. Although there are more modern methods for making requests, understanding XMLHttpRequest is valuable for historical context and compatibility with older browsers.

Creating an XMLHttpRequest Object

To make an HTTP request using XMLHttpRequest, you first need to create an instance of the object.

const xhr = new XMLHttpRequest();

Opening a Request

After creating the XMLHttpRequest object, you need to specify the request details, including the HTTP method (e.g., GET or POST) and the URL to which the request will be sent.

xhr.open("GET", "https://api.example.com/data", true);
  • The first argument is the HTTP method, such as GET or POST.
  • The second argument is the URL to which the request will be sent.
  • The third argument indicates whether the request should be asynchronous (true) or synchronous (false). Asynchronous is the preferred option to avoid blocking the UI thread.

Handling Events

XMLHttpRequest provides event listeners to handle various stages of the request. The most common events are:

  • onload: Fired when the request completes successfully.
  • onerror: Fired when an error occurs.
  • onabort: Fired when the request is aborted.
xhr.onload = function () {
  if (xhr.status === 200) {
    // Request succeeded; handle the response
    console.log(xhr.responseText);
  } else {
    // Request failed; handle the error
    console.error("Request failed with status:", xhr.status);
  }
};

Sending a Request

After configuring the request, you can send it using the send() method.

xhr.send();

Handling Responses

The response from the server can be accessed through the responseText or responseXML properties of the XMLHttpRequest object.

xhr.onload = function () {
  if (xhr.status === 200) {
    const data = JSON.parse(xhr.responseText);
    console.log(data);
  }
};

Handling Errors

Handling errors is essential when working with HTTP requests. The onerror event is triggered if an error occurs during the request.

xhr.onerror = function () {
  console.error("An error occurred.");
};

Handling Progress

XMLHttpRequest provides events for tracking the progress of a request. For instance, the onprogress event can be used to monitor the progress of data transmission.

xhr.onprogress = function (event) {
  if (event.lengthComputable) {
    const percentComplete = (event.loaded / event.total) * 100;
    console.log("Progress: " + percentComplete + "%");
  }
};

Aborting a Request

You can abort a request at any time by calling the abort() method on the XMLHttpRequest object.

xhr.abort();

Limitations of XMLHttpRequest

  • Cross-Origin Restrictions: XMLHttpRequest follows the same-origin policy, which means it can only make requests to the same domain from which the web page originated. To make cross-origin requests, you might need to use server-side proxies or modern alternatives like the Fetch API.
  • Verbosity: Using XMLHttpRequest can be verbose and complex, especially for handling various aspects of the request and response.

Fetch API

The Fetch API is a modern replacement for XMLHttpRequest and provides a more straightforward and flexible way to make HTTP requests. It returns Promises, simplifying asynchronous code.

Making a Basic GET Request

Here’s how to make a simple GET request using the Fetch API:

fetch("https://api.example.com/data")
  .then(response => {
    if (!response.ok) {
      throw new Error("Network response was not ok");
    }
    return response.json(); // Parse the response as JSON
  })
  .then(data => {
    console.log(data);
  })
  .catch(error => {
    console.error(error);
  });
  • fetch() returns a Promise that resolves to the Response to that request, whether it is successful or not.
  • The ok property of the Response object is a boolean that indicates whether the request was successful (status code in the range 200-299).
  • The json() method of the Response object parses the response as JSON.

Making POST Requests

To make a POST request, you need to provide additional options in the fetch() call:

fetch("https://api.example.com/data", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ key: "value" }),
})
  .then(response => {
    if (!response.ok) {
      throw new Error("Network response was not ok");
    }
    return response.json();
  })
  .then(data => {
    console.log(data);
  })
  .catch(error => {
    console.error(error);
  });
  • The method option specifies the HTTP method, which can be “GET,” “POST,” “PUT,” “DELETE,” and others.
  • The headers option sets the request headers.
  • The body option contains the data to be sent in the request. It should be a string, typically in JSON format.

Handling CORS

The Fetch API supports Cross-Origin Resource Sharing (CORS) headers, which allows web pages to make requests to different domains. The server must also respond with the appropriate CORS headers to enable cross-origin requests.

Fetch API Advantages

  • Simplicity: The Fetch API uses Promises, making it more straightforward to work with asynchronous code.
  • Flexibility: It provides more options and control over requests and responses.
  • Modern: It is the recommended approach for making HTTP requests in modern web development.

Axios

Axios is a popular JavaScript library for making HTTP requests. It simplifies working with HTTP requests and provides a clean and consistent API. Axios is especially useful for projects that require a more comprehensive and convenient way to manage requests and responses.

Installing Axios

To use Axios, you first need to install it. You can do this using npm or yarn:

npm install axios
# or
yarn add axios

Making GET and POST Requests

Axios provides methods for making GET and POST requests.

Making a GET Request:

const axios = require("axios");
axios.get("https://api.example.com/data")
  .then(response => {
    console.log(response.data);
  })
  .catch(error => {
    console.error(error);
  });

Making a POST Request:

const axios = require("axios");
axios.post("https://api.example.com/data", { key: "value" })
  .then(response => {
    console.log(response.data);
  })
  .catch(error => {
    console.error(error);
  });

Axios automatically parses JSON responses, making it more convenient when working with JSON-based APIs.

Handling Errors

Axios provides a convenient way to handle HTTP errors using the catch method. It captures any HTTP errors and allows you to respond to them in a standardized manner.

axios.get("https://api.example.com/data")
  .then(response => {
    console.log(response.data);
  })
  .catch(error => {
    if (error.response) {
      // The request was made, but the server responded with a non-2xx status code
      console.error("Server responded with status:", error.response.status);
    } else if (error.request) {
      // The request was made, but there was no response
      console.error("No response received");
    } else {
      // Something happened in setting up the request
      console.error("Error:", error.message);
    }
  });

Axios Interceptors

Axios provides a powerful feature called interceptors, which allows you to globally intercept and modify requests and responses. Interceptors are useful for tasks such as adding authentication tokens to requests or handling errors consistently.

// Add an interceptor to all requests
axios.interceptors.request.use(
  config => {
    // Modify the request config here (e.g., add an authorization header)
    config.headers.Authorization = "Bearer myAccessToken";
    return config;
  },
  error => {
    return Promise.reject(error);
  }
);
// Add an interceptor to all responses
axios.interceptors.response.use(
  response => {
    // Modify the response data here
    return response;
  },
  error => {
    // Handle any response errors globally
    console.error("Response error:", error);
    return Promise.reject(error);
  }
);

Fetch vs. Axios

Both Fetch and Axios are widely used for making HTTP requests in modern web development. Each has its advantages and disadvantages, so the choice depends on your project’s requirements.

Fetch:

  • Native API: Fetch is built into modern browsers, making it a native solution.
  • Promises: It returns Promises, making it more modern and compatible with modern JavaScript patterns.
  • Standardized: It follows the evolving Fetch standard.
  • Lightweight: It is a lightweight API, which can be a pro for simple use cases.
  • Basic: Fetch provides a fundamental set of features, allowing for extensibility via other JavaScript libraries or custom code.

Axios:

  • Convenient: Axios simplifies HTTP requests and responses, making it a preferred choice for many developers.
  • Interceptors: It offers powerful interceptors for global request/response handling.
  • Error Handling: Axios provides consistent error handling with standardized error objects.
  • Flexibility: It is a more versatile and extensible library, allowing for customization.
  • Community Support: Axios has a robust community, providing additional features and plugins.

In summary, Fetch is suitable for simple use cases and is the preferred choice if you want to avoid external libraries. Axios, on the other hand, offers more convenience, robust error handling, and powerful features like interceptors, making it a great choice for complex applications.

Working with Data Formats

When making HTTP requests, you often deal with various data formats. Two common formats are JSON (JavaScript Object Notation) and XML (eXtensible Markup Language).

Handling JSON Data

JSON is a lightweight data interchange format that is easy to read and write. JavaScript provides built-in methods for parsing JSON and converting JavaScript objects to JSON.

Parsing JSON

To parse a JSON string and convert it into a JavaScript object, you can use the JSON.parse() method:

const jsonData = '{"name": "Alice", "age": 30}';
const parsedData = JSON.parse(jsonData);
console.log(parsedData.name); // Outputs: "Alice"
console.log(parsedData.age);  // Outputs: 30

Converting to JSON

To convert a JavaScript object to a JSON string, use the JSON.stringify() method:

const person = { name: "Bob", age: 25 };
const jsonString = JSON.stringify(person);
console.log(jsonString); // Outputs: '{"name":"Bob","age":25}'

Handling XML Data

XML is a more complex and less human-readable format than JSON. JavaScript does not provide native XML parsing methods like it does for JSON. To work with XML, you can use libraries like DOMParser.

Parsing XML

const xmlString = '<book><title>JavaScript for Beginners</title><author>John Doe</author></book>';
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xmlString, "text/xml");
const title = xmlDoc.getElementsByTagName("title")[0].textContent;
const author = xmlDoc.getElementsByTagName("author")[0].textContent;
console.log(title);  // Outputs: "JavaScript for Beginners"
console.log(author); // Outputs: "John Doe"

Conclusion

Understanding AJAX and HTTP requests in JavaScript is vital for modern web development. Asynchronous requests enable dynamic, responsive web applications that can interact with web servers and retrieve data without requiring full page reloads.

You have learned about the XMLHttpRequest object, the Fetch API, and the Axios library as methods for making HTTP requests. Each method has its advantages and use cases, so you can choose the one that best fits your project’s requirements.

Additionally, you’ve seen how to handle common data formats such as JSON and XML when working with HTTP responses. Properly parsing and processing data is crucial for building robust web applications that can communicate effectively with server-side resources.

Scroll to Top