Vue.js HTTP Requests: Error Handling, Authentication, and File Uploads

Vue.js, with its simplicity and reactivity, is not only a front-end framework but also excels in facilitating communication between the client and server through HTTP requests. In this article, we will explore four advanced examples that go beyond the basics, showcasing the power and flexibility of Vue HTTP requests.

1. Real-Time Data Polling with Fetch

Imagine a scenario where you need to fetch real-time data from a server at regular intervals. The standard fetch method can be extended to achieve this by using JavaScript's setInterval function. Let's create a component that fetches the latest stock prices every 5 seconds.

<!-- RealTimeStocks.vue -->

<template>
  <div>
    <h2>Real-Time Stock Prices</h2>
    <ul>
      <li v-for="stock in stocks" :key="stock.symbol">
        {{ stock.symbol }}: {{ stock.price }}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      stocks: [],
    };
  },
  mounted() {
    this.fetchStocks(); // Initial fetch
    setInterval(this.fetchStocks, 5000); // Fetch every 5 seconds
  },
  methods: {
    async fetchStocks() {
      const response = await fetch("https://api.example.com/stocks");
      this.stocks = await response.json();
    },
  },
};
</script>

In this example, the mounted lifecycle hook initiates the first fetch, and then we use setInterval it to fetch the latest stock prices every 5 seconds. This approach ensures that the data stays up-to-date in real-time.

2. Handling HTTP Errors Gracefully

Error handling is a critical aspect of robust web applications. Vue provides a clean way to handle HTTP errors by checking the ok properties of the Response object. Let's create a component that displays an error message if the HTTP request fails.

<!-- ErrorHandling.vue -->

<template>
  <div>
    <h2>Fetching Data with Error Handling</h2>
    <button @click="fetchData">Fetch Data</button>
    <p v-if="error">{{ error }}</p>
    <pre v-else>{{ data }}</pre>
  </div>
</template>

<script>
export default {
  data() {
    return {
      data: null,
      error: null,
    };
  },
  methods: {
    async fetchData() {
      try {
        const response = await fetch("https://api.example.com/data");
        if (!response.ok) {
          throw new Error("Failed to fetch data");
        }
        this.data = await response.text();
        this.error = null; // Reset error if successful
      } catch (error) {
        this.error = "Error fetching data: " + error.message;
        this.data = null; // Reset data on error
      }
    },
  },
};
</script>

Here, we use a try...catch block to catch any errors that may occur during the HTTP request. If an error occurs, the catch block sets the error data property, and if the request is successful, it sets the data property.

3. Authentication with Bearer Token

Many modern applications require authentication to access protected resources. Let's create a component that fetches user data after authenticating with a Bearer token.

<!-- Authentication.vue -->

<template>
  <div>
    <h2>User Profile</h2>
    <button @click="fetchUserProfile">Fetch Profile</button>
    <pre v-if="user">{{ user }}</pre>
    <p v-if="error">{{ error }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      user: null,
      error: null,
    };
  },
  methods: {
    async fetchUserProfile() {
      try {
        const token = "Bearer YOUR_ACCESS_TOKEN"; // Replace with your actual token
        const response = await fetch("https://api.example.com/profile", {
          headers: {
            Authorization: token,
          },
        });
        if (!response.ok) {
          throw new Error("Failed to fetch user profile");
        }
        this.user = await response.json();
        this.error = null;
      } catch (error) {
        this.error = "Error fetching user profile: " + error.message;
        this.user = null;
      }
    },
  },
};
</script>

In this example, we include the Bearer token in the request headers for authentication. Adjust the token variable with your actual access token.

4. Uploading Files with FormData

Uploading files is a common requirement in web applications. Let's create a component that allows users to upload an image file.

<!-- FileUpload.vue -->

<template>
  <div>
    <h2>File Upload</h2>
    <input type="file" @change="handleFileChange" />
    <button @click="uploadFile">Upload</button>
    <p v-if="error">{{ error }}</p>
    <img :src="imageUrl" alt="Uploaded Image" v-if="imageUrl" />
  </div>
</template>

<script>
export default {
  data() {
    return {
      file: null,
      imageUrl: null,
      error: null,
    };
  },
  methods: {
    handleFileChange(event) {
      this.file = event.target.files[0];
    },
    async uploadFile() {
      try {
        const formData = new FormData();
        formData.append("image", this.file);

        const response = await fetch("https://api.example.com/upload", {
          method: "POST",
          body: formData,
        });

        if (!response.ok) {
          throw new Error("Failed to upload file");
        }

        const { url } = await response.json();
        this.imageUrl = url;
        this.error = null;
      } catch (error) {
        this.error = "Error uploading file: " + error.message;
        this.imageUrl = null;
      }
    },
  },
};
</script>

This example uses the FormData object to construct a form with the uploaded file, and the fetch method is configured to send a POST request with the form data. The advanced examples provided showcase the versatility and power of Vue.js in handling various aspects of HTTP requests, elevating your web development capabilities. From real-time data polling to graceful error handling, authentication with Bearer tokens, and seamless file uploads, Vue.js proves to be a robust framework that empowers developers to create dynamic and interactive applications.

By mastering Vue.js in the realm of HTTP requests, you gain the ability to build applications that not only fetch and display data but also respond intelligently to errors, authenticate users securely, and facilitate the exchange of files seamlessly. These examples serve as a stepping stone for developers to explore and integrate Vue.js with diverse backend services and APIs, ultimately enhancing the user experience and functionality of web applications.

As you delve deeper into Vue.js and its capabilities in handling HTTP requests, consider experimenting with these examples, customizing them to suit your specific project requirements, and exploring additional features provided by Vue.js to further optimize your development workflow.

Sharing 3 exercises that are designed to reinforce your understanding. See the attachment.