【AJAX】AJAX详解

文章目录

  • [AJAX 使用说明](#AJAX 使用说明)
    • [一、AJAX 简介](#一、AJAX 简介)
    • [二、AJAX 工作原理](#二、AJAX 工作原理)
    • [三、AJAX 核心 API](#三、AJAX 核心 API)
      • [1. 创建 XMLHttpRequest 对象](#1. 创建 XMLHttpRequest 对象)
      • [2. Fetch API(现代替代方案)](#2. Fetch API(现代替代方案))
    • [四、XMLHttpRequest 完整使用示例](#四、XMLHttpRequest 完整使用示例)
    • [五、AJAX 请求状态 (readyState)](#五、AJAX 请求状态 (readyState))
    • 六、常用请求方法示例
      • [1. GET 请求(获取数据)](#1. GET 请求(获取数据))
      • [2. POST 请求(提交数据)](#2. POST 请求(提交数据))
    • [七、Fetch API 使用示例](#七、Fetch API 使用示例)
    • 八、错误处理与超时控制
    • 九、最佳实践
    • 十、完整示例:用户搜索功能
    • 总结

AJAX 使用说明

一、AJAX 简介

AJAX(Asynchronous JavaScript and XML)是一种在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页内容的技术。

主要特点:

  • 异步通信:后台与服务器交换数据,不阻塞用户界面
  • 局部更新:只更新网页的某一部分,无需刷新整个页面
  • 多种数据格式:支持 XML、JSON、HTML、文本等

二、AJAX 工作原理

用户 浏览器 XMLHttpRequest 服务器 触发事件(点击/输入等) 创建XHR对象 发送异步请求 处理请求 查询数据库/执行操作 返回响应数据 触发回调函数 更新页面局部内容 用户 浏览器 XMLHttpRequest 服务器

三、AJAX 核心 API

1. 创建 XMLHttpRequest 对象

复制代码
// 现代浏览器
const xhr = new XMLHttpRequest();

// 兼容旧版IE (IE6及以下)
if (window.ActiveXObject) {
    xhr = new ActiveXObject("Microsoft.XMLHTTP");
}

2. Fetch API(现代替代方案)

javascript 复制代码
fetch(url, options)
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error('Error:', error));

四、XMLHttpRequest 完整使用示例

javascript 复制代码
// 1. 创建XHR对象
const xhr = new XMLHttpRequest();

// 2. 配置请求
xhr.open('GET', 'https://api.example.com/data', true); // true表示异步

// 3. 设置请求头(可选)
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Authorization', 'Bearer token123');

// 4. 定义响应处理函数
xhr.onreadystatechange = function() {
    if (xhr.readyState === 4) { // 请求完成
        if (xhr.status === 200) { // 成功响应
            const data = JSON.parse(xhr.responseText);
            console.log('成功:', data);
            updateUI(data);
        } else {
            console.error('请求失败:', xhr.status, xhr.statusText);
            handleError(xhr.status);
        }
    }
};

// 5. 处理加载进度(可选)
xhr.onprogress = function(event) {
    if (event.lengthComputable) {
        const percentComplete = (event.loaded / event.total) * 100;
        console.log(`加载进度: ${percentComplete}%`);
    }
};

// 6. 处理错误(可选)
xhr.onerror = function() {
    console.error('网络请求错误');
};

// 7. 发送请求
xhr.send();

// 对于POST请求,需要传递数据
// xhr.send(JSON.stringify({key: 'value'}));

五、AJAX 请求状态 (readyState)

0: UNSENT 1: OPENED 2: HEADERS_RECEIVED 3: LOADING 4: DONE

状态说明:

  • 0 (UNSENT):XHR对象已创建,但open()未调用
  • 1 (OPENED):open()已调用,但send()未调用
  • 2 (HEADERS_RECEIVED):send()已调用,响应头已接收
  • 3 (LOADING):响应体正在下载中
  • 4 (DONE):请求完成,响应就绪

六、常用请求方法示例

1. GET 请求(获取数据)

javascript 复制代码
function getData(url, callback) {
    const xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    xhr.onload = function() {
        if (xhr.status === 200) {
            callback(null, JSON.parse(xhr.responseText));
        } else {
            callback(new Error(`请求失败: ${xhr.status}`));
        }
    };
    xhr.onerror = function() {
        callback(new Error('网络错误'));
    };
    xhr.send();
}

2. POST 请求(提交数据)

javascript 复制代码
function postData(url, data, callback) {
    const xhr = new XMLHttpRequest();
    xhr.open('POST', url, true);
    xhr.setRequestHeader('Content-Type', 'application/json');
    
    xhr.onload = function() {
        if (xhr.status >= 200 && xhr.status < 300) {
            callback(null, JSON.parse(xhr.responseText));
        } else {
            callback(new Error(`请求失败: ${xhr.status}`));
        }
    };
    
    xhr.onerror = function() {
        callback(new Error('网络错误'));
    };
    
    xhr.send(JSON.stringify(data));
}

七、Fetch API 使用示例

javascript 复制代码
// GET 请求
fetch('https://api.example.com/data')
    .then(response => {
        if (!response.ok) {
            throw new Error('网络响应异常');
        }
        return response.json();
    })
    .then(data => {
        console.log('数据:', data);
    })
    .catch(error => {
        console.error('错误:', error);
    });

// POST 请求
fetch('https://api.example.com/data', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        name: 'John',
        age: 30
    })
})
.then(response => response.json())
.then(data => console.log('成功:', data))
.catch(error => console.error('错误:', error));

八、错误处理与超时控制

javascript 复制代码
// 超时设置
xhr.timeout = 10000; // 10秒超时
xhr.ontimeout = function() {
    console.error('请求超时');
};

// 使用Promise封装AJAX
function ajaxPromise(method, url, data = null) {
    return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open(method, url, true);
        
        if (data && method === 'POST') {
            xhr.setRequestHeader('Content-Type', 'application/json');
        }
        
        xhr.onload = function() {
            if (xhr.status >= 200 && xhr.status < 300) {
                resolve(JSON.parse(xhr.responseText));
            } else {
                reject(new Error(`HTTP ${xhr.status}: ${xhr.statusText}`));
            }
        };
        
        xhr.onerror = function() {
            reject(new Error('网络请求失败'));
        };
        
        xhr.ontimeout = function() {
            reject(new Error('请求超时'));
        };
        
        xhr.send(data ? JSON.stringify(data) : null);
    });
}

// 使用示例
ajaxPromise('GET', 'https://api.example.com/data')
    .then(data => console.log(data))
    .catch(error => console.error(error));

九、最佳实践

  1. 添加加载指示器:在请求期间显示加载状态
  2. 防抖/节流:避免频繁请求,特别是在搜索框中
  3. 错误友好提示:给用户清晰的错误反馈
  4. 取消请求:必要时取消未完成的请求
  5. 安全考虑
    • 验证和清理用户输入
    • 使用HTTPS
    • 实施CORS策略
    • 防止CSRF攻击

十、完整示例:用户搜索功能

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <style>
        #loading { display: none; color: blue; }
        .error { color: red; }
        .user-item { padding: 5px; border-bottom: 1px solid #ccc; }
    </style>
</head>
<body>
    <input type="text" id="searchInput" placeholder="搜索用户...">
    <div id="loading">加载中...</div>
    <div id="results"></div>
    <div id="error" class="error"></div>

    <script>
        let currentRequest = null;
        let searchTimeout = null;
        
        document.getElementById('searchInput').addEventListener('input', function(e) {
            const query = e.target.value.trim();
            
            // 清除之前的超时
            clearTimeout(searchTimeout);
            
            if (query.length < 2) {
                document.getElementById('results').innerHTML = '';
                return;
            }
            
            // 显示加载指示器
            document.getElementById('loading').style.display = 'block';
            document.getElementById('error').innerHTML = '';
            
            // 防抖:延迟500ms执行搜索
            searchTimeout = setTimeout(() => {
                searchUsers(query);
            }, 500);
        });
        
        function searchUsers(query) {
            // 取消之前的请求
            if (currentRequest) {
                currentRequest.abort();
            }
            
            // 创建新请求
            const xhr = new XMLHttpRequest();
            currentRequest = xhr;
            
            xhr.open('GET', `https://api.example.com/users?q=${encodeURIComponent(query)}`, true);
            
            xhr.onload = function() {
                document.getElementById('loading').style.display = 'none';
                
                if (xhr.status === 200) {
                    const users = JSON.parse(xhr.responseText);
                    displayResults(users);
                } else {
                    document.getElementById('error').innerHTML = '搜索失败,请重试';
                }
                currentRequest = null;
            };
            
            xhr.onerror = function() {
                document.getElementById('loading').style.display = 'none';
                document.getElementById('error').innerHTML = '网络连接错误';
                currentRequest = null;
            };
            
            xhr.send();
        }
        
        function displayResults(users) {
            const resultsDiv = document.getElementById('results');
            
            if (users.length === 0) {
                resultsDiv.innerHTML = '<p>未找到用户</p>';
                return;
            }
            
            resultsDiv.innerHTML = users.map(user => 
                `<div class="user-item">${user.name} - ${user.email}</div>`
            ).join('');
        }
    </script>
</body>
</html>

总结

AJAX 是现代Web应用的核心技术之一,它使得网页能够实现更流畅的用户体验。虽然现在有更现代的 Fetch API 和基于 Promise 的解决方案,但理解传统的 XMLHttpRequest 工作原理仍然很重要,因为:

  1. 兼容性:某些旧项目仍在使用
  2. 进度监控:XHR 支持上传/下载进度跟踪
  3. 基础知识:理解底层机制有助于使用更高级的库(如 Axios)

根据项目需求,可以选择:

  • 原生 XHR:需要精细控制或兼容旧浏览器时
  • Fetch API:现代浏览器,需要简洁语法时
  • Axios 等库:需要拦截器、取消请求等高级功能时
相关推荐
FreeBuf_1 小时前
430万Chrome与Edge用户遭ShadyPanda恶意软件七年攻击
前端·chrome·edge
小毛驴8501 小时前
查看 npm 源的常用命令
前端·npm·node.js
JosieBook1 小时前
【Vue】01 Vue技术——Vue简介
前端·javascript·vue.js
HIT_Weston1 小时前
48、【Ubuntu】【Gitlab】拉出内网 Web 服务:Nginx 事件驱动分析(二)
前端·ubuntu·gitlab
EB_Coder1 小时前
前端面试题-JavaScript中级篇
前端·javascript·面试
Beginner x_u1 小时前
从接口文档到前端调用:Axios 封装与实战全流程详解
前端·javascript·ajax·接口·axios
7澄11 小时前
Servlet 前后端交互实战(登录/注册案例)
运维·服务器·ajax·servlet·jquery·form·前后端交互
HIT_Weston1 小时前
46、【Ubuntu】【Gitlab】拉出内网 Web 服务:http.server 分析(三)
前端·ubuntu·gitlab