Skip to content
Marcelo XP edited this page Jan 17, 2025 · 7 revisions

Introduction

The JsBaseClass library comes with Axios built-in, making it effortless to handle HTTP requests without the need for additional setup. Axios, a widely-used HTTP client, is seamlessly integrated into JsBaseClass, allowing you to focus on writing clean and efficient code. This page provides a comprehensive guide and practical examples to help you handle common scenarios, such as making GET/POST requests, sending form data, and managing UI states like loading indicators.


Why Use Axios with JsBaseClass?

  • Simplified HTTP Requests: Axios provides a clean and intuitive API for making HTTP requests.
  • Error Handling: Built-in support for handling errors gracefully.
  • UI State Management: Easily manage loading states and user feedback.
  • Structured Logging: Use this.console for consistent and color-coded logging.

Basic Example: GET Request

Here's a basic example of how to make a GET request using Axios within a class that extends JsBaseClass:

class ClassAxios extends JsBaseClass {
    async onDomContentLoaded() {
        // Ensure the DOM is fully loaded before making the request
        await this.getData(); // Fetch data from a valid API
    }

    async getData() {
        try {
            this.console.info(`1️⃣ Before Get Data`);
            const response = await axios.get('https://jsonplaceholder.typicode.com/todos/1');
            this.console.log(`✅ Get Data`, response.data);
        } catch (error) {
            this.console.log(`🚨 ${error.message}`, error);
        } finally {
            this.console.log(`2️⃣ After Get Data`);
        }
    }
}

// Initialize the example
window.objAxios = new ClassAxios();
objAxios.init();

Handling Errors

Axios makes it easy to handle errors, such as network issues or invalid responses:

class ClassAxios extends JsBaseClass {
    async onDomContentLoaded() {
        await this.getNonExistsData(); // Attempt to fetch data from a non-existent API
    }

    async getNonExistsData() {
        try {
            this.console.info(`1️⃣ Before Get Non Exists Data`);
            const response = await axios.get('https://not-exists/json/1');
            this.console.log(response.data);
        } catch (error) {
            this.console.log(`🚨 ${error.message}`, error);
        } finally {
            this.console.log(`2️⃣ After Get Non Exists Data`);
        }
    }
}

// Initialize the example
window.objAxios = new ClassAxios();
objAxios.init();

Managing UI States

When making HTTP requests, it's important to provide feedback to the user, such as showing a loading indicator during the request and hiding it afterward. This enhances the user experience by visually indicating that a process is in progress.


JavaScript Code

The following example demonstrates how to manage UI states effectively using a loading indicator:

class ClassLoading extends JsBaseClass {
    showLoading() {
        // Create and display a loading spinner
        const loadingSpinner = document.createElement('div');
        loadingSpinner.id = 'loading-spinner';
        loadingSpinner.textContent = 'Uploading...';
        loadingSpinner.style = `
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: rgba(0, 0, 0, 0.75);
            color: white;
            padding: 10px 20px;
            border-radius: 5px;
            font-size: 16px;
        `;
        document.body.appendChild(loadingSpinner);
    }

    hideLoading() {
        // Remove the loading spinner
        const loadingSpinner = document.getElementById('loading-spinner');
        if (loadingSpinner) {
            loadingSpinner.remove();
        }
    }

    async onDomContentLoaded() {
        try {
            this.showLoading(); // Show loading before making the request
            const response = await axios.get('https://jsonplaceholder.typicode.com/posts/1');
            this.console.log(`✅ Request Successful`, response.data);
        } catch (error) {
            this.console.error(`🚨 Request Failed: ${error.message}`);
        } finally {
            this.hideLoading(); // Hide loading regardless of success or failure
        }
    }
}

// Initialize and trigger the example
window.objLoading = new ClassLoading();
objLoading.init();

Key Concepts: Try and Finally

  • Why Use try?
    The try block contains the code that may throw an error, such as an HTTP request. If the request succeeds, the code in the try block runs as expected.

  • Why Use finally?
    The finally block is executed after the try block, whether the request succeeds or fails (even if an error occurs). This ensures that the loading indicator is always hidden, preventing it from getting stuck on the screen.


How It Works

  1. Before the Request:

    • The showLoading method is called to display the loading spinner.
  2. During the Request:

    • The try block attempts to make an HTTP request. If the request is successful, the response is logged in the console.
  3. If an Error Occurs:

    • The catch block handles the error and logs it for debugging.
  4. After the Request:

    • The finally block ensures the hideLoading method is called, removing the loading spinner regardless of the outcome.

Example Console Output

Success Case:

✅ Request Successful { id: 1, title: 'Example Title', ... }

Error Case:

🚨 Request Failed: Network Error

Why Managing UI States Is Crucial

  • Improved User Experience: Visual feedback reassures users that their actions are being processed.
  • Error Resilience: Using finally ensures the UI remains consistent, even in failure scenarios.
  • Professionalism: A loading indicator prevents users from thinking the application is unresponsive.

By following this approach, you can manage loading states efficiently, ensuring a smoother and more professional user experience. 🚀


Sending Form Data with POST

The JsBaseClass library simplifies HTTP requests by integrating Axios directly, allowing you to send form data with ease. This section demonstrates how to handle form submissions and send data via a POST request using a straightforward example.


HTML Form

Start by creating a simple HTML form for collecting user data:

<form id="contactForm">
    <label for="name">Name:</label>
    <input type="text" id="name" name="name" required>

    <label for="email">Email:</label>
    <input type="email" id="email" name="email" required>

    <label for="message">Message:</label>
    <textarea id="message" name="message" required></textarea>

    <button type="submit">Submit</button>
</form>

JavaScript Code

The following JavaScript class demonstrates how to handle the form submission and send data using the POST method:

class ClassAxios extends JsBaseClass {
    async onDomContentLoaded() {
        // Bind the form submission event
        const form = document.getElementById('contactForm');
        form.addEventListener('submit', async (event) => {
            event.preventDefault(); // Prevent the default form submission (page reload)
            await this.submitForm(); // Submit form data
        });
    }

    async submitForm() {
        // Retrieve form data
        const formData = {
            name: document.getElementById('name').value,
            email: document.getElementById('email').value,
            message: document.getElementById('message').value,
        };

        try {
            window.objLoading.showLoading();
            const response = await axios.post('https://jsonplaceholder.typicode.com/posts', formData);
            this.console.log(`✅ Form Submitted`, response.data);
        } catch (error) {
            this.console.log(`🚨 ${error.message}`, error);
        } finally {
            window.objLoading.hideLoading();
        }
    }
}

// Initialize the example
window.objAxios = new ClassAxios();
objAxios.init();

How It Works

  1. HTML Form:

    • The form provides fields for the user to input their name, email, and message.
    • The form's submit event is captured and managed via JavaScript.
  2. JavaScript Class:

    • The handle method binds the form submission event to the submitForm method.
    • The submitForm method collects the data entered in the form and sends it via an Axios POST request.
    • Logs are used to provide a clear flow of the process, including success and error messages.

Advanced Example: Uploading Files

Here's how to upload files using Axios. This example uses FormData to handle file uploads, which is essential for sending binary data like images or documents.

class ClassAxios extends JsBaseClass {
    async onDomContentLoaded() {
        await this.onUploadFile();
    }

    async onUploadFile() {
        const fileInput = document.getElementById('fileInput');
        fileInput.onchange = async (event) => {
            const file = event.target.files[0];
            const formData = new FormData();
            formData.append('file', file); // Add the file to the FormData object

            try {
                window.objLoading.showLoading();
                this.console.info(`1️⃣ Before Upload File`);
                const response = await axios.post('https://example.com/upload', formData, {
                    headers: {
                        'Content-Type': 'multipart/form-data', // Required for file uploads
                    },
                });
                this.console.log(`✅ File Uploaded`, response.data);
            } catch (error) {
                this.console.log(`🚨 ${error.message}`, error);
            } finally {
                window.objLoading.hideLoading();
                this.console.log(`2️⃣ After Upload File`);
            }
        };

        // Trigger file selection
        fileInput.click();
    }
}

// Initialize the example
window.objAxios = new ClassAxios();
objAxios.init();

Key Concepts

  1. Loading Indicators:

    • Always show a loading indicator when making asynchronous requests.
    • Ensure the indicator is hidden in the finally block to guarantee it disappears, regardless of the request outcome.
  2. Error Handling:

    • Use try/catch to handle errors gracefully and provide user feedback.
  3. Form Data:

    • Use FormData to send form data, including files, via POST requests.
  4. UI Feedback:

    • Provide clear feedback to the user, such as success messages or error alerts.
  5. Form Validation:

    • Validate form data before sending it to the server to reduce unnecessary requests and improve user experience.
    • Use HTML5 validation attributes (e.g., required, type="email") or custom JavaScript validation logic.

Example Output in Console

1️⃣ Before Get Data
✅ Get Data { userId: 1, id: 1, title: 'delectus aut autem', completed: false }
2️⃣ After Get Data

Best Practices

  1. Modular Code:

    • Separate HTTP request logic into methods for reusability and clarity.
  2. Consistent Logging:

    • Use this.console for structured logging to make debugging easier.
  3. User Feedback:

    • Always provide feedback to the user, such as loading indicators or success/error messages.
  4. Error Recovery:

    • Offer options for users to retry failed requests or correct errors.

With these examples and concepts, you can efficiently handle HTTP requests, manage UI states, and provide a seamless user experience using JsBaseClass and Axios. 🚀


Using Custom Headers with Axios

Custom headers are often required to interact with APIs that require authentication or other specific metadata. Below is an example of how to use Axios to send a POST request with custom headers, replicating the following cURL request:

curl "https://api.groq.com/openai/v1/chat/completions" \
  -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${GROQ_API_KEY}" \
  -d '{
         "messages": [
           {
             "role": "system",
             "content": "You are a front-end javascript expert."
           },
           {
             "role": "user",
             "content": "crie uma função para converter uma string em um slug."
           }
         ],
         "model": "llama-3.3-70b-versatile",
         "temperature": 1,
         "max_completion_tokens": 1024,
         "top_p": 1,
         "stream": true,
         "stop": null
       }'

Code Example

Below is the equivalent implementation in JavaScript using Axios with the ClassGroq structure:

class ClassGroq extends JsBaseClass {
    constructor(groqApiKey) {
        super();
        this.groqApiKey = groqApiKey;
    }
    
    async onDomContentLoaded() {
        // Ensure the DOM is fully loaded before making the request
        await this.askToGroqAi();
    }

    async askToGroqAi() {
        try {
            this.console.info(`🚀 Sending Custom Request`);

            const url = "https://api.groq.com/openai/v1/chat/completions";
            const headers = {
                "Content-Type": "application/json",
                "Authorization": `Bearer ${this.groqApiKey}`,
            };
            const data = {
                messages: [
                    { role: "system", content: "You are a front-end javascript expert." },
                    { role: "user", content: "Create a function to convert a string to a slug." },
                ],
                model: "llama-3.3-70b-versatile",
                temperature: 1,
                max_completion_tokens: 1024,
                top_p: 1,
                stream: true,
                stop: null,
            };

            const response = await axios.post(url, data, { headers });
            this.console.log(`✅ Response Data:`, response.data);
        } catch (error) {
            this.console.error(`🚨 Error: ${error.message}`, error);
        } finally {
            this.console.info(`🏁 Request Completed`);
        }
    }
}

// Initialize the example
window.objGroq = new ClassGroq("GROQ_API_KEY"); // Replace GROQ_API_KEY with your actual key
objGroq.init();

Explanation

  1. Headers:

    • Custom headers are passed as an object in the headers field of the axios.post method.
    • In this case:
      • Content-Type: Specifies that the body of the request is JSON.
      • Authorization: Passes the Bearer token (GROQ_API_KEY) required for authentication.
  2. Payload:

    • The data object mirrors the JSON payload in the cURL command.
    • It contains the messages array, model information, and additional parameters like temperature, max_completion_tokens, etc.
  3. Error Handling:

    • The try...catch...finally block ensures any errors during the request are logged and that post-request logic is always executed.

This approach ensures a seamless and modular way to integrate API calls with custom headers into your projects.

Clone this wiki locally