Skip to content

AJAX原理与实现

前言

AJAX (Asynchronous JavaScript and XML) 是现代Web应用的核心技术之一,它允许网页异步地与服务器交换数据,而无需刷新整个页面。本文将深入探讨AJAX的原理和实现方式。

一、AJAX工作原理

1.1 基本流程

┌──────────┐    1.发送请求     ┌──────────┐
│  浏览器   │ ───────────────> │  服务器   │
│          │ <─────────────── │          │
└──────────┘    2.响应数据     └──────────┘
     │                              │
     │ 3.局部更新                   │
     ↓                              │
┌──────────┐                        │
│   DOM    │                        │
└──────────┘                        │

1.2 核心组件

  • XMLHttpRequest对象
  • 服务器端接口
  • DOM操作方法

二、XMLHttpRequest详解

2.1 基础用法

javascript
// 创建XHR对象
const xhr = new XMLHttpRequest();

// 配置请求
xhr.open('GET', '/api/data', true);

// 设置响应类型
xhr.responseType = 'json';

// 监听状态变化
xhr.onreadystatechange = function() {
    if (xhr.readyState === 4 && xhr.status === 200) {
        console.log(xhr.response);
    }
};

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

2.2 readyState状态码

javascript
const ReadyState = {
    UNSENT: 0,           // 初始化状态
    OPENED: 1,           // open()方法已调用
    HEADERS_RECEIVED: 2, // 收到响应头
    LOADING: 3,          // 响应数据接收中
    DONE: 4             // 请求完成
};

三、现代AJAX封装

3.1 Promise版本

javascript
function ajax(options = {}) {
    // 默认配置
    const defaultOptions = {
        url: '',
        method: 'GET',
        data: null,
        headers: {
            'Content-Type': 'application/json'
        },
        responseType: 'json',
        timeout: 0
    };

    // 合并配置
    options = { ...defaultOptions, ...options };

    return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();

        // 超时处理
        if (options.timeout) {
            xhr.timeout = options.timeout;
            xhr.ontimeout = () => reject(new Error('请求超时'));
        }

        // 错误处理
        xhr.onerror = () => reject(new Error('网络错误'));

        // 状态监听
        xhr.onreadystatechange = function() {
            if (xhr.readyState === 4) {
                if (xhr.status >= 200 && xhr.status < 300) {
                    resolve(xhr.response);
                } else {
                    reject(new Error(`HTTP Error: ${xhr.status}`));
                }
            }
        };

        // 处理GET请求参数
        if (options.method === 'GET' && options.data) {
            const params = new URLSearchParams(options.data);
            options.url += `?${params.toString()}`;
        }

        // 打开连接
        xhr.open(options.method, options.url, true);

        // 设置响应类型
        xhr.responseType = options.responseType;

        // 设置请求头
        Object.entries(options.headers).forEach(([key, value]) => {
            xhr.setRequestHeader(key, value);
        });

        // 发送请求
        xhr.send(options.method === 'POST' ? JSON.stringify(options.data) : null);
    });
}

3.2 使用示例

javascript
// GET请求
ajax({
    url: '/api/users',
    method: 'GET',
    data: { page: 1, size: 10 }
})
.then(response => console.log(response))
.catch(error => console.error(error));

// POST请求
ajax({
    url: '/api/users',
    method: 'POST',
    data: { name: 'John', age: 30 },
    headers: {
        'Authorization': 'Bearer token'
    }
})
.then(response => console.log(response))
.catch(error => console.error(error));

四、实际应用最佳实践

4.1 错误处理

javascript
async function fetchData() {
    try {
        const response = await ajax({
            url: '/api/data',
            timeout: 5000
        });
        return response;
    } catch (error) {
        if (error.message === '请求超时') {
            // 超时重试逻辑
            return retryFetch();
        }
        // 其他错误处理
        console.error('请求失败:', error);
        throw error;
    }
}

4.2 并发请求

javascript
async function fetchMultipleData() {
    try {
        const [users, posts] = await Promise.all([
            ajax({ url: '/api/users' }),
            ajax({ url: '/api/posts' })
        ]);
        return { users, posts };
    } catch (error) {
        console.error('并发请求失败:', error);
        throw error;
    }
}

总结

  1. AJAX的核心是XMLHttpRequest对象
  2. 现代AJAX实现应该:
    • 使用Promise封装
    • 支持错误处理
    • 提供超时机制
    • 支持请求配置
  3. 实际应用中要注意:
    • 错误处理
    • 超时处理
    • 并发请求
    • 状态管理