Skip to content

jQuery AJAX 和异步请求

AJAX(Asynchronous JavaScript and XML)是现代 Web 应用的核心技术之一,它允许网页在不重新加载整个页面的情况下与服务器进行异步数据交换。jQuery 提供了强大而易用的 AJAX 功能,大大简化了异步请求的处理。本章将详细介绍如何使用 jQuery 进行 AJAX 操作。

AJAX 基础

什么是 AJAX?

AJAX 是一种在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术。它基于以下技术:

  • XMLHttpRequest 对象(与服务器异步交换数据)
  • JavaScript/DOM(显示/获取数据)
  • CSS(设置数据样式)
  • XML/JSON(数据格式)

jQuery AJAX 的优势

  • 简化了原生 XMLHttpRequest 的复杂性
  • 提供了统一的 API
  • 自动处理数据格式转换
  • 支持多种数据类型
  • 提供了丰富的回调函数

jQuery AJAX 方法

1. $.ajax() 方法(核心方法)

这是 jQuery AJAX 的核心方法,提供了最完整的功能:

javascript
$.ajax({
    url: 'api/data',           // 请求地址
    type: 'GET',              // 请求方法(GET、POST、PUT、DELETE等)
    dataType: 'json',         // 预期服务器返回的数据类型
    data: {                   // 发送到服务器的数据
        key1: 'value1',
        key2: 'value2'
    },
    beforeSend: function(xhr) {
        // 请求发送前的回调函数
        console.log('请求即将发送');
    },
    success: function(data, textStatus, xhr) {
        // 请求成功后的回调函数
        console.log('请求成功', data);
    },
    error: function(xhr, textStatus, errorThrown) {
        // 请求失败后的回调函数
        console.log('请求失败', textStatus, errorThrown);
    },
    complete: function(xhr, textStatus) {
        // 请求完成后的回调函数(无论成功或失败都会执行)
        console.log('请求完成');
    }
});

2. 便捷方法

$.get() 方法

发送 GET 请求:

javascript
// 基本用法
$.get('api/data', function(data) {
    console.log(data);
});

// 带参数的 GET 请求
$.get('api/data', { id: 123 }, function(data) {
    console.log(data);
});

// 完整参数
$.get('api/data', { id: 123 }, function(data) {
    console.log(data);
}, 'json');

$.post() 方法

发送 POST 请求:

javascript
// 基本用法
$.post('api/data', function(data) {
    console.log(data);
});

// 带数据的 POST 请求
$.post('api/data', {
    name: 'John',
    email: 'john@example.com'
}, function(data) {
    console.log(data);
});

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

$.getJSON() 方法

获取 JSON 数据:

javascript
// 基本用法
$.getJSON('api/data.json', function(data) {
    console.log(data);
});

// 带参数的请求
$.getJSON('api/data.json', { id: 123 }, function(data) {
    console.log(data);
});

AJAX 选项详解

1. 基本选项

javascript
$.ajax({
    // 请求地址
    url: 'api/data',
    
    // 请求方法
    type: 'POST',  // 或 'GET', 'PUT', 'DELETE' 等
    
    // 发送到服务器的数据
    data: {
        name: 'John',
        age: 30
    },
    
    // 预期服务器返回的数据类型
    dataType: 'json',  // 'xml', 'html', 'script', 'json', 'jsonp', 'text'
    
    // 发送数据到服务器时使用的数据类型
    contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
    
    // 请求超时时间(毫秒)
    timeout: 5000,
    
    // 是否缓存请求结果
    cache: false,
    
    // 是否异步执行
    async: true,
    
    // 是否触发全局 AJAX 事件
    global: true
});

2. 回调函数选项

javascript
$.ajax({
    url: 'api/data',
    
    // 请求发送前调用
    beforeSend: function(xhr, settings) {
        // 可以修改 XMLHttpRequest 对象
        // 返回 false 可以取消请求
        console.log('请求发送前');
    },
    
    // 请求成功时调用
    success: function(data, textStatus, xhr) {
        // data: 服务器返回的数据
        // textStatus: 状态文本
        // xhr: XMLHttpRequest 对象
        console.log('请求成功', data);
    },
    
    // 请求失败时调用
    error: function(xhr, textStatus, errorThrown) {
        // xhr: XMLHttpRequest 对象
        // textStatus: 错误类型
        // errorThrown: 异常对象
        console.log('请求失败', textStatus, errorThrown);
    },
    
    // 请求完成后调用(无论成功或失败)
    complete: function(xhr, textStatus) {
        // 总是会执行
        console.log('请求完成');
    }
});

数据类型处理

1. JSON 数据

javascript
$.ajax({
    url: 'api/user',
    dataType: 'json',
    success: function(data) {
        // data 已经被自动解析为 JavaScript 对象
        console.log(data.name);
        console.log(data.email);
    }
});

2. XML 数据

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

3. HTML 数据

javascript
$.ajax({
    url: 'api/content.html',
    dataType: 'html',
    success: function(html) {
        // html 是字符串
        $('#content').html(html);
    }
});

4. 文本数据

javascript
$.ajax({
    url: 'api/data.txt',
    dataType: 'text',
    success: function(text) {
        // text 是字符串
        console.log(text);
    }
});

表单数据提交

1. 序列化表单数据

javascript
// 序列化整个表单
$('#myForm').submit(function(event) {
    event.preventDefault();
    
    $.ajax({
        url: 'api/submit',
        type: 'POST',
        data: $(this).serialize(),
        success: function(response) {
            console.log('表单提交成功', response);
        }
    });
});

// 序列化部分表单元素
var formData = $('#myForm input, #myForm select').serialize();

2. 手动构建表单数据

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

文件上传

使用 FormData 进行文件上传

javascript
$('#uploadForm').submit(function(event) {
    event.preventDefault();
    
    var formData = new FormData(this);
    
    $.ajax({
        url: 'api/upload',
        type: 'POST',
        data: formData,
        processData: false,  // 不处理数据
        contentType: false,  // 不设置内容类型
        success: function(response) {
            console.log('文件上传成功', response);
        },
        error: function(xhr, status, error) {
            console.log('文件上传失败', error);
        }
    });
});

AJAX 事件

jQuery 提供了全局 AJAX 事件,可以在任何地方监听 AJAX 请求的状态:

javascript
// AJAX 请求开始时触发
$(document).ajaxStart(function() {
    $('#loading').show();
});

// AJAX 请求结束时触发
$(document).ajaxStop(function() {
    $('#loading').hide();
});

// AJAX 请求成功时触发
$(document).ajaxSuccess(function(event, xhr, settings) {
    console.log('AJAX 请求成功');
});

// AJAX 请求失败时触发
$(document).ajaxError(function(event, xhr, settings, thrownError) {
    console.log('AJAX 请求失败');
});

错误处理

1. HTTP 状态码处理

javascript
$.ajax({
    url: 'api/data',
    success: function(data) {
        console.log('成功', data);
    },
    error: function(xhr, status, error) {
        switch(xhr.status) {
            case 404:
                console.log('请求的资源未找到');
                break;
            case 500:
                console.log('服务器内部错误');
                break;
            default:
                console.log('请求失败', error);
        }
    }
});

2. 超时处理

javascript
$.ajax({
    url: 'api/slow-data',
    timeout: 5000,  // 5秒超时
    success: function(data) {
        console.log('数据获取成功', data);
    },
    error: function(xhr, status, error) {
        if (status === 'timeout') {
            console.log('请求超时');
        } else {
            console.log('请求失败', error);
        }
    }
});

Promise 方式处理 AJAX

jQuery AJAX 返回的是 Promise 对象,可以使用 Promise 语法:

javascript
// 使用 Promise 方式
$.ajax({
    url: 'api/data',
    type: 'GET'
}).then(
    function(data) {
        // 成功回调
        console.log('成功', data);
    },
    function(xhr, status, error) {
        // 失败回调
        console.log('失败', error);
    }
);

// 链式调用
$.ajax({
    url: 'api/data1'
}).then(function(data1) {
    console.log('第一个请求完成', data1);
    return $.ajax({
        url: 'api/data2',
        data: { id: data1.id }
    });
}).then(function(data2) {
    console.log('第二个请求完成', data2);
}).catch(function(error) {
    console.log('请求出错', error);
});

完整示例

以下是一个展示 jQuery AJAX 功能的完整示例:

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>jQuery AJAX 示例</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, textarea {
            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 示例</h1>
    
    <div class="container">
        <h2>基本 AJAX 请求</h2>
        <button id="getData">获取数据</button>
        <button id="postData">发送数据</button>
        <div class="loading" id="loading1">加载中...</div>
        <div class="result" id="result1">结果将显示在这里</div>
    </div>
    
    <div class="container">
        <h2>表单提交</h2>
        <form id="userForm">
            <input type="text" id="userName" placeholder="姓名" required>
            <input type="email" id="userEmail" placeholder="邮箱" required>
            <select id="userCountry">
                <option value="">选择国家</option>
                <option value="cn">中国</option>
                <option value="us">美国</option>
                <option value="uk">英国</option>
            </select>
            <button type="submit">提交表单</button>
        </form>
        <div class="loading" id="loading2">提交中...</div>
        <div class="result" id="result2">表单提交结果将显示在这里</div>
    </div>
    
    <div class="container">
        <h2>AJAX 事件监听</h2>
        <button id="testAjaxEvents">测试 AJAX 事件</button>
        <div class="loading" id="loading3">测试中...</div>
        <div class="result" id="result3">AJAX 事件结果将显示在这里</div>
    </div>
    
    <div class="container">
        <h2>错误处理</h2>
        <button id="testError">测试错误处理</button>
        <button id="testTimeout">测试超时</button>
        <div class="loading" id="loading4">测试中...</div>
        <div class="result" id="result4">错误处理结果将显示在这里</div>
    </div>
    
    <script>
        $(function() {
            // 全局 AJAX 事件
            $(document).ajaxStart(function() {
                $('.loading').show();
            }).ajaxStop(function() {
                $('.loading').hide();
            });
            
            // 基本 AJAX 请求示例
            $('#getData').click(function() {
                $.ajax({
                    url: 'https://jsonplaceholder.typicode.com/posts/1',
                    type: 'GET',
                    dataType: 'json',
                    success: function(data) {
                        $('#result1').html('<div class="success">获取数据成功:</div><pre>' + JSON.stringify(data, null, 2) + '</pre>');
                    },
                    error: function(xhr, status, error) {
                        $('#result1').html('<div class="error">获取数据失败:' + error + '</div>');
                    }
                });
            });
            
            $('#postData').click(function() {
                $.ajax({
                    url: 'https://jsonplaceholder.typicode.com/posts',
                    type: 'POST',
                    data: {
                        title: '测试标题',
                        body: '测试内容',
                        userId: 1
                    },
                    dataType: 'json',
                    success: function(data) {
                        $('#result1').html('<div class="success">发送数据成功:</div><pre>' + JSON.stringify(data, null, 2) + '</pre>');
                    },
                    error: function(xhr, status, error) {
                        $('#result1').html('<div class="error">发送数据失败:' + error + '</div>');
                    }
                });
            });
            
            // 表单提交示例
            $('#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">请填写完整信息!</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">表单提交成功:</div><pre>' + JSON.stringify(data, null, 2) + '</pre>');
                        // 清空表单
                        $('#userForm')[0].reset();
                    },
                    error: function(xhr, status, error) {
                        $('#result2').html('<div class="error">表单提交失败:' + error + '</div>');
                    }
                });
            });
            
            // AJAX 事件监听示例
            $('#testAjaxEvents').click(function() {
                $('#result3').html('开始测试 AJAX 事件...');
                
                $.ajax({
                    url: 'https://jsonplaceholder.typicode.com/posts/1',
                    type: 'GET',
                    dataType: 'json',
                    success: function(data) {
                        $('#result3').append('<br><div class="success">AJAX 请求成功完成</div>');
                    }
                });
            });
            
            // 错误处理示例
            $('#testError').click(function() {
                $.ajax({
                    url: 'https://jsonplaceholder.typicode.com/nonexistent',
                    type: 'GET',
                    dataType: 'json',
                    success: function(data) {
                        $('#result4').html('<div class="success">请求成功</div>');
                    },
                    error: function(xhr, status, error) {
                        var errorMessage = '';
                        switch(xhr.status) {
                            case 404:
                                errorMessage = '请求的资源未找到 (404)';
                                break;
                            case 500:
                                errorMessage = '服务器内部错误 (500)';
                                break;
                            default:
                                errorMessage = '请求失败:' + error;
                        }
                        $('#result4').html('<div class="error">' + errorMessage + '</div>');
                    }
                });
            });
            
            $('#testTimeout').click(function() {
                $.ajax({
                    url: 'https://httpbin.org/delay/3', // 故意延迟的 API
                    type: 'GET',
                    timeout: 2000, // 2秒超时
                    success: function(data) {
                        $('#result4').html('<div class="success">请求成功</div>');
                    },
                    error: function(xhr, status, error) {
                        if (status === 'timeout') {
                            $('#result4').html('<div class="error">请求超时</div>');
                        } else {
                            $('#result4').html('<div class="error">请求失败:' + error + '</div>');
                        }
                    }
                });
            });
        });
    </script>
</body>
</html>

通过本章的学习,你应该掌握了如何使用 jQuery 进行 AJAX 操作和异步请求处理。在下一章中,我们将学习 jQuery 插件的开发和使用。