Quiz 2

Frontend-Backend Integration — AJAX and Fetch API

904 words
5 min read
Python Week 1: the first filter for runtime behavior
Visual companion
Python
Type and operator map

Python Week 1: the first filter for runtime behavior

View
Revision summary

What this note is really saying

Short form

# Frontend-Backend Integration — AJAX and Fetch API ## 🎯 Learning Objectives - Use Fetch API to make HTTP requests from JavaScript - Send and receive JSON data with the backend - Handle CORS errors - Build dynamic UIs that update without page reload - Handle loading and error states ## 1. What is AJAX?

Frontend-Backend Integration — AJAX and Fetch API

🎯 Learning Objectives

  • Use Fetch API to make HTTP requests from JavaScript
  • Send and receive JSON data with the backend
  • Handle CORS errors
  • Build dynamic UIs that update without page reload
  • Handle loading and error states

1. What is AJAX?

AJAX (Asynchronous JavaScript and XML) allows web pages to send/receive data from a server without reloading the page. Despite the "XML" in the name, JSON is now the standard format. Without AJAX: Submit form → page reloads → wait for full response. With AJAX: Click button → fetch data in background → update only the relevant part of the page.

2. The Fetch API

Modern browsers provide fetch() for making HTTP requests:
javascript
// Basic GET request
fetch('/api/books')
    .then(response => response.json())  // Parse JSON
    .then(data => {
        console.log(data);  // Array of books
        displayBooks(data);
    })
    .catch(error => {
        console.error('Error:', error);
    });

2.1 Async/Await Syntax (Cleaner)

javascript
async function loadBooks() {
    try {
        const response = await fetch('/api/books');
        if (!response.ok) {
            throw new Error(`HTTP ${response.status}`);
        }
        const books = await response.json();
        displayBooks(books);
    } catch (error) {
        showError('Failed to load books');
    }
}

2.2 POST Request with JSON

javascript
async function addBook(title, author) {
    try {
        const response = await fetch('/api/books', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({ title, author })
        });
        if (!response.ok) {
            const error = await response.json();
            throw new Error(error.error);
        }
        const newBook = await response.json();
        return newBook;
    } catch (error) {
        showError(error.message);
    }
}

3. Complete Example: Book List App

Backend (Flask): Same as the REST API (earlier topic) Frontend (HTML + JS):
html
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
    <title>Book Manager</title>
</head>
<body>
    <h1>Books</h1>
    <form id="addBookForm">
        <input type="text" id="title" placeholder="Title" required>
        <input type="text" id="author" placeholder="Author" required>
        <button type="submit">Add Book</button>
    </form>
    <ul id="bookList"></ul>
    <script>
        const API = '/api/books';
        // Load books on page load
        async function loadBooks() {
            const response = await fetch(API);
            const books = await response.json();
            const list = document.getElementById('bookList');
            list.innerHTML = books.map(book => `
                <li>
                    <strong>${book.title}</strong> by ${book.author}
                    <button onclick="deleteBook(${book.id})">Delete</button>
                </li>
            `).join('');
        }
        // Add book
        document.getElementById('addBookForm').addEventListener('submit', async (e) => {
            e.preventDefault();
            const title = document.getElementById('title').value;
            const author = document.getElementById('author').value;
            await fetch(API, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ title, author })
            });
            document.getElementById('title').value = '';
            document.getElementById('author').value = '';
            loadBooks();  // Refresh the list
        });
        // Delete book
        async function deleteBook(id) {
            await fetch(`${API}/${id}`, { method: 'DELETE' });
            loadBooks();  // Refresh the list
        }
        // Initial load
        loadBooks();
    </script>
</body>
</html>

4. CORS (Cross-Origin Resource Sharing)

When frontend and backend are on different origins (domain, port, or protocol), the browser blocks requests:
pseudo
Origin: http://localhost:3000 (React dev server)
Request to: http://localhost:5000 (Flask API)
→ CORS error!
Flask-CORS fix:
python
# pip install flask-cors
from flask_cors import CORS
app = Flask(__name__)
CORS(app)  # Allow all origins (development only)
# For production, restrict origins:
CORS(app, origins=['https://myapp.com'])

5. Practice Questions

Q1: What is AJAX and why is it used?
Answer: AJAX allows web pages to send/receive data from a server without reloading the entire page. This creates smoother user experiences (dynamic updates, partial page refreshes, real-time validation). Q2: How does the fetch() API work?
Answer: fetch(url, options) returns a Promise that resolves to a Response object. You call response.json() (or .text(), .blob()) to extract the body. Use async/await or .then() chains. Q3: What is CORS and when does it matter?
Answer: CORS (Cross-Origin Resource Sharing) is a browser security mechanism that blocks requests from a different origin (domain, port, protocol). It matters when your frontend (e.g., on port 3000) talks to a backend on a different port (e.g., 5000). The server must include CORS headers to allow this. Q4: How do you handle errors with fetch?
Answer: Check response.ok (true for 200-299 status codes). If false, read the error response with response.json() or response.text(). Use try/catch for network errors. Q5: What is the purpose of e.preventDefault() in form handlers?
Answer: Prevents the browser's default form submission behavior (which would reload the page). When using AJAX, we want to handle submission via JavaScript instead. Q6: How do you send JSON data with fetch?
Answer: Set the method to POST/PUT, set Content-Type: application/json header, and pass the data as JSON.stringify(obj) in the body:
javascript
fetch('/api/data', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ key: 'value' })
});
Q7: Why do we need the async keyword before functions using await?
Answer: await can only be used inside functions declared with async. An async function automatically returns a Promise (wrapping the return value). This is how JavaScript implements asynchronous operations. Q8: How would you show a loading spinner during an AJAX request?
javascript
async function loadData() {
    showSpinner();  // Show loading indicator
    try {
        const data = await fetch('/api/data').then(r => r.json());
        displayData(data);
    } catch (error) {
        showError(error);
    } finally {
        hideSpinner();  // Always hide when done
    }
}

📐 Key Concepts

ConceptFrontendBackend
GET datafetch('/api/items')return jsonify(items)
POST datafetch(url, {method:'POST', body: JSON.stringify(data)})request.get_json()
JSON formatresponse.json()jsonify()
Error handlingif (!response.ok)return jsonify(error), 400
CORSBrowser blocks cross-originCORS(app) to allow

🔗 Cross-References

Document outline

Keep your place and jump directly to a heading.

Table of Contents
System Normal // Awaiting Context

Intelligence Hub

Navigate the knowledge graph to generate context. The Hub adapts dynamically to surface backlinks, related notes, and metadata insights.