jQuery AJAX and Asynchronous Requests

AJAX (Asynchronous JavaScript and XML) is a core technology of modern web applications that allows web pages to exchange data with servers asynchronously without reloading the entire page. jQuery provides powerful and easy-to-use AJAX functionality that greatly simplifies asynchronous request handling. This chapter covers how to perform AJAX operations using jQuery.

AJAX Basics

What is AJAX?

AJAX is a technique for exchanging data with a server and updating parts of a web page without reloading the entire page. It's based on:

  • XMLHttpRequest object (asynchronous data exchange with server)
  • JavaScript/DOM (display/retrieve data)
  • CSS (style data)
  • XML/JSON (data formats)

jQuery AJAX Advantages

  • Simplifies complexity of native XMLHttpRequest
  • Provides unified API
  • Automatically handles data format conversion
  • Supports multiple data types
  • Offers rich callback functions

jQuery AJAX Methods

1. $.ajax() Method (Core Method)

This is jQuery's core AJAX method with full functionality:

$.ajax({
    url: 'api/data',           // Request URL
    type: 'GET',              // Request method (GET, POST, PUT, DELETE, etc.)
    dataType: 'json',         // Expected server response data type
    data: {                   // Data sent to server
        key1: 'value1',
        key2: 'value2'
    },
    beforeSend: function(xhr) {
        // Callback before request is sent
        console.log('Request about to be sent');
    },
    success: function(data, textStatus, xhr) {
        // Callback on successful request
        console.log('Request successful', data);
    },
    error: function(xhr, textStatus, errorThrown) {
        // Callback on failed request
        console.log('Request failed', textStatus, errorThrown);
    },
    complete: function(xhr, textStatus) {
        // Callback after request completes (success or failure)
        console.log('Request complete');
    }
});

2. Shorthand Methods

$.get() Method

Send GET request:

// Basic usage
$.get('api/data', function(data) {
    console.log(data);
});

// GET request with parameters
$.get('api/data', { id: 123 }, function(data) {
    console.log(data);
});

// Full parameters
$.get('api/data', { id: 123 }, function(data) {
    console.log(data);
}, 'json');

$.post() Method

Send POST request:

// Basic usage
$.post('api/data', function(data) {
    console.log(data);
});

// POST request with data
$.post('api/data', {
    name: 'John',
    email: 'john@example.com'
}, function(data) {
    console.log(data);
});

// Full parameters
$.post('api/data', {
    name: 'John',
    email: 'john@example.com'
}, function(data) {
    console.log(data);
}, 'json');

$.getJSON() Method

Get JSON data:

// Basic usage
$.getJSON('api/data.json', function(data) {
    console.log(data);
});

// Request with parameters
$.getJSON('api/data.json', { id: 123 }, function(data) {
    console.log(data);
});

AJAX Options Explained

1. Basic Options

$.ajax({
    // Request URL
    url: 'api/data',
    
    // Request method
    type: 'POST',  // or 'GET', 'PUT', 'DELETE', etc.
    
    // Data sent to server
    data: {
        name: 'John',
        age: 30
    },
    
    // Expected server response data type
    dataType: 'json',  // 'xml', 'html', 'script', 'json', 'jsonp', 'text'
    
    // Content type when sending data
    contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
    
    // Request timeout (milliseconds)
    timeout: 5000,
    
    // Whether to cache request results
    cache: false,
    
    // Whether to execute asynchronously
    async: true,
    
    // Whether to trigger global AJAX events
    global: true
});

2. Callback Options

$.ajax({
    url: 'api/data',
    
    // Called before request is sent
    beforeSend: function(xhr, settings) {
        // Can modify XMLHttpRequest object
        // Return false to cancel request
        console.log('Before send');
    },
    
    // Called on successful request
    success: function(data, textStatus, xhr) {
        // data: Server response data
        // textStatus: Status text
        // xhr: XMLHttpRequest object
        console.log('Success', data);
    },
    
    // Called on failed request
    error: function(xhr, textStatus, errorThrown) {
        // xhr: XMLHttpRequest object
        // textStatus: Error type
        // errorThrown: Exception object
        console.log('Error', textStatus, errorThrown);
    },
    
    // Called after request completes (success or failure)
    complete: function(xhr, textStatus) {
        // Always executes
        console.log('Complete');
    }
});

Data Type Handling

1. JSON Data

$.ajax({
    url: 'api/user',
    dataType: 'json',
    success: function(data) {
        // data is automatically parsed to JavaScript object
        console.log(data.name);
        console.log(data.email);
    }
});

2. XML Data

$.ajax({
    url: 'api/data.xml',
    dataType: 'xml',
    success: function(xml) {
        // xml is XML DOM object
        $(xml).find('item').each(function() {
            var title = $(this).find('title').text();
            console.log(title);
        });
    }
});

3. HTML Data

$.ajax({
    url: 'api/content.html',
    dataType: 'html',
    success: function(html) {
        // html is string
        $('#content').html(html);
    }
});

Form Data Submission

1. Serialize Form Data

// Serialize entire form
$('#myForm').submit(function(event) {
    event.preventDefault();
    
    $.ajax({
        url: 'api/submit',
        type: 'POST',
        data: $(this).serialize(),
        success: function(response) {
            console.log('Form submitted successfully', response);
        }
    });
});

// Serialize partial form elements
var formData = $('#myForm input, #myForm select').serialize();

2. Manually Build Form Data

$.ajax({
    url: 'api/submit',
    type: 'POST',
    data: {
        name: $('#name').val(),
        email: $('#email').val(),
        message: $('#message').val()
    },
    success: function(response) {
        console.log('Submitted successfully', response);
    }
});

File Upload

Using FormData for File Upload

$('#uploadForm').submit(function(event) {
    event.preventDefault();
    
    var formData = new FormData(this);
    
    $.ajax({
        url: 'api/upload',
        type: 'POST',
        data: formData,
        processData: false,  // Don't process data
        contentType: false,  // Don't set content type
        success: function(response) {
            console.log('File uploaded successfully', response);
        },
        error: function(xhr, status, error) {
            console.log('File upload failed', error);
        }
    });
});

AJAX Events

jQuery provides global AJAX events that can listen to AJAX request status anywhere:

// Triggered when AJAX request starts
$(document).ajaxStart(function() {
    $('#loading').show();
});

// Triggered when AJAX request ends
$(document).ajaxStop(function() {
    $('#loading').hide();
});

// Triggered on successful AJAX request
$(document).ajaxSuccess(function(event, xhr, settings) {
    console.log('AJAX request successful');
});

// Triggered on failed AJAX request
$(document).ajaxError(function(event, xhr, settings, thrownError) {
    console.log('AJAX request failed');
});

Error Handling

1. HTTP Status Code Handling

$.ajax({
    url: 'api/data',
    success: function(data) {
        console.log('Success', data);
    },
    error: function(xhr, status, error) {
        switch(xhr.status) {
            case 404:
                console.log('Resource not found');
                break;
            case 500:
                console.log('Internal server error');
                break;
            default:
                console.log('Request failed', error);
        }
    }
});

2. Timeout Handling

$.ajax({
    url: 'api/slow-data',
    timeout: 5000,  // 5 second timeout
    success: function(data) {
        console.log('Data retrieved successfully', data);
    },
    error: function(xhr, status, error) {
        if (status === 'timeout') {
            console.log('Request timed out');
        } else {
            console.log('Request failed', error);
        }
    }
});

Promise-based AJAX

jQuery AJAX returns a Promise object, allowing Promise syntax:

// Using Promise syntax
$.ajax({
    url: 'api/data',
    type: 'GET'
}).then(
    function(data) {
        // Success callback
        console.log('Success', data);
    },
    function(xhr, status, error) {
        // Error callback
        console.log('Failed', error);
    }
);

// Chained calls
$.ajax({
    url: 'api/data1'
}).then(function(data1) {
    console.log('First request complete', data1);
    return $.ajax({
        url: 'api/data2',
        data: { id: data1.id }
    });
}).then(function(data2) {
    console.log('Second request complete', data2);
}).catch(function(error) {
    console.log('Request error', error);
});

Complete Example

Here's a complete example demonstrating jQuery AJAX functionality:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>jQuery AJAX Example</title>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <style>
        .container { border: 1px solid #ccc; padding: 20px; margin: 10px 0; }
        .result {
            margin: 10px 0; padding: 10px;
            background-color: #f8f9fa; border-radius: 4px; min-height: 50px;
        }
        .loading { display: none; color: #007bff; }
        button {
            margin: 5px; padding: 8px 15px;
            background-color: #007bff; color: white;
            border: none; border-radius: 4px; cursor: pointer;
        }
        button:hover { background-color: #0056b3; }
        input, select { margin: 5px; padding: 8px; border: 1px solid #ccc; border-radius: 4px; }
        .error { color: red; font-weight: bold; }
        .success { color: green; font-weight: bold; }
    </style>
</head>
<body>
    <h1>jQuery AJAX Example</h1>
    
    <div class="container">
        <h2>Basic AJAX Request</h2>
        <button id="getData">Get Data</button>
        <button id="postData">Send Data</button>
        <div class="loading" id="loading1">Loading...</div>
        <div class="result" id="result1">Results will display here</div>
    </div>
    
    <div class="container">
        <h2>Form Submission</h2>
        <form id="userForm">
            <input type="text" id="userName" placeholder="Name" required>
            <input type="email" id="userEmail" placeholder="Email" required>
            <select id="userCountry">
                <option value="">Select Country</option>
                <option value="us">USA</option>
                <option value="uk">UK</option>
                <option value="ca">Canada</option>
            </select>
            <button type="submit">Submit Form</button>
        </form>
        <div class="result" id="result2">Form results will display here</div>
    </div>
    
    <div class="container">
        <h2>Error Handling</h2>
        <button id="testError">Test Error</button>
        <button id="testTimeout">Test Timeout</button>
        <div class="result" id="result4">Error handling results will display here</div>
    </div>
    
    <script>
        $(function() {
            // Global AJAX events
            $(document).ajaxStart(function() {
                $('.loading').show();
            }).ajaxStop(function() {
                $('.loading').hide();
            });
            
            // Basic AJAX request
            $('#getData').click(function() {
                $.ajax({
                    url: 'https://jsonplaceholder.typicode.com/posts/1',
                    type: 'GET',
                    dataType: 'json',
                    success: function(data) {
                        $('#result1').html('<div class="success">Data retrieved:</div><pre>' + JSON.stringify(data, null, 2) + '</pre>');
                    },
                    error: function(xhr, status, error) {
                        $('#result1').html('<div class="error">Failed: ' + error + '</div>');
                    }
                });
            });
            
            $('#postData').click(function() {
                $.ajax({
                    url: 'https://jsonplaceholder.typicode.com/posts',
                    type: 'POST',
                    data: { title: 'Test Title', body: 'Test Content', userId: 1 },
                    dataType: 'json',
                    success: function(data) {
                        $('#result1').html('<div class="success">Data sent:</div><pre>' + JSON.stringify(data, null, 2) + '</pre>');
                    },
                    error: function(xhr, status, error) {
                        $('#result1').html('<div class="error">Failed: ' + error + '</div>');
                    }
                });
            });
            
            // Form submission
            $('#userForm').submit(function(event) {
                event.preventDefault();
                var formData = {
                    name: $('#userName').val(),
                    email: $('#userEmail').val(),
                    country: $('#userCountry').val()
                };
                
                if (!formData.name || !formData.email || !formData.country) {
                    $('#result2').html('<div class="error">Please fill in all fields!</div>');
                    return;
                }
                
                $.ajax({
                    url: 'https://jsonplaceholder.typicode.com/users',
                    type: 'POST',
                    data: JSON.stringify(formData),
                    contentType: 'application/json; charset=utf-8',
                    dataType: 'json',
                    success: function(data) {
                        $('#result2').html('<div class="success">Form submitted:</div><pre>' + JSON.stringify(data, null, 2) + '</pre>');
                        $('#userForm')[0].reset();
                    },
                    error: function(xhr, status, error) {
                        $('#result2').html('<div class="error">Failed: ' + error + '</div>');
                    }
                });
            });
            
            // Error handling
            $('#testError').click(function() {
                $.ajax({
                    url: 'https://jsonplaceholder.typicode.com/nonexistent',
                    type: 'GET',
                    error: function(xhr, status, error) {
                        var msg = xhr.status === 404 ? 'Resource not found (404)' : 'Request failed: ' + error;
                        $('#result4').html('<div class="error">' + msg + '</div>');
                    }
                });
            });
            
            $('#testTimeout').click(function() {
                $.ajax({
                    url: 'https://httpbin.org/delay/3',
                    type: 'GET',
                    timeout: 2000,
                    success: function(data) {
                        $('#result4').html('<div class="success">Success</div>');
                    },
                    error: function(xhr, status, error) {
                        var msg = status === 'timeout' ? 'Request timed out' : 'Failed: ' + error;
                        $('#result4').html('<div class="error">' + msg + '</div>');
                    }
                });
            });
        });
    </script>
</body>
</html>

Through this chapter, you should have mastered how to perform AJAX operations and asynchronous request handling using jQuery. In the next chapter, we'll learn about jQuery plugin development and usage.