【js篇】深入理解 AJAX 及其实现

46 阅读3分钟

AJAX(Asynchronous JavaScript and XML)是现代 Web 开发的基石技术之一,它让网页能够异步更新,无需刷新整个页面即可与服务器交换数据并更新部分内容。


✅ 一句话总结

AJAX 是通过 XMLHttpRequest 对象实现浏览器与服务器的异步通信,可以局部更新页面。现代开发中通常使用 Promisefetch API 封装 AJAX 请求,提升代码可读性和可维护性。


✅ 一、什么是 AJAX?

🔹 定义

AJAX(Asynchronous JavaScript and XML)是一种异步通信技术,允许 JavaScript 向服务器发送 HTTP 请求并处理响应,而无需刷新整个页面

🔹 核心优势

  • 局部更新:只更新需要变化的部分,提升用户体验;
  • 减少带宽消耗:无需传输整个页面;
  • 提升响应速度:用户感觉更流畅;
  • 实现动态交互:如搜索建议、表单验证、无限滚动等;

🔹 技术组成

  • XMLHttpRequest 对象(核心)
  • JavaScript(控制逻辑)
  • HTML/CSS(页面结构与样式)
  • JSON/XML(数据格式,现代多用 JSON)

✅ 二、原生 AJAX 请求实现步骤

🔹 1. 创建 XMLHttpRequest 对象

const xhr = new XMLHttpRequest();

🔹 2. 配置请求:open(method, url, async, user, password)

xhr.open('GET', '/api/data', true);
  • method:请求方法(GET、POST、PUT、DELETE 等)
  • url:请求地址
  • async:是否异步(通常为 true
  • user/password:可选认证信息

🔹 3. 设置请求头(可选)

xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Accept', 'application/json');

🔹 4. 设置响应数据类型

xhr.responseType = 'json'; // 自动解析 JSON
// 其他选项:'text', 'document', 'blob', 'arraybuffer'

🔹 5. 监听状态变化:onreadystatechange

XMLHttpRequest 有 5 个 readyState 状态:

状态说明
UNSENT0未初始化
OPENED1已调用 open()
HEADERS_RECEIVED2已收到响应头
LOADING3正在接收响应体
DONE4请求完成
xhr.onreadystatechange = function() {
  if (xhr.readyState !== 4) return; // 等待完成
  
  if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {
    console.log(xhr.response); // 成功处理数据
  } else {
    console.error('请求失败:', xhr.statusText);
  }
};

🔹 6. 处理错误

xhr.onerror = function() {
  console.error('网络错误');
};

🔹 7. 发送请求

xhr.send(null); // GET 请求无数据体
// POST 请求:xhr.send(JSON.stringify(data));

✅ 三、完整原生 AJAX 示例

function ajaxRequest(url, options = {}) {
  const xhr = new XMLHttpRequest();
  
  // 默认配置
  const method = options.method || 'GET';
  const data = options.data || null;
  
  xhr.open(method, url, true);
  
  // 设置请求头
  if (options.headers) {
    Object.keys(options.headers).forEach(key => {
      xhr.setRequestHeader(key, options.headers[key]);
    });
  }
  
  // 响应类型
  xhr.responseType = options.responseType || 'json';
  
  // 成功回调
  xhr.onreadystatechange = function() {
    if (xhr.readyState === 4) {
      if (xhr.status >= 200 && xhr.status < 300) {
        options.success && options.success(xhr.response);
      } else {
        options.error && options.error(xhr.statusText);
      }
    }
  };
  
  // 错误处理
  xhr.onerror = function() {
    options.error && options.error('网络错误');
  };
  
  xhr.send(data);
}

// 使用
ajaxRequest('/api/users', {
  success: function(data) {
    console.log('用户列表:', data);
  },
  error: function(err) {
    console.error('请求失败:', err);
  }
});

✅ 四、使用 Promise 封装 AJAX(推荐)

原生 XMLHttpRequest 回调嵌套复杂,使用 Promise 可以让代码更清晰。

function getJSON(url) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    
    xhr.open('GET', url, true);
    xhr.responseType = 'json';
    xhr.setRequestHeader('Accept', 'application/json');
    
    xhr.onreadystatechange = function() {
      if (xhr.readyState !== 4) return;
      
      if (xhr.status === 200) {
        resolve(xhr.response);
      } else {
        reject(new Error(xhr.statusText));
      }
    };
    
    xhr.onerror = function() {
      reject(new Error('网络错误'));
    };
    
    xhr.send();
  });
}

// 使用 Promise
getJSON('/api/data')
  .then(data => console.log(data))
  .catch(err => console.error(err));

✅ 五、现代替代方案:fetch API

fetch 是现代浏览器提供的更简洁的异步请求方案,基于 Promise

// 使用 fetch
fetch('/api/data')
  .then(response => {
    if (!response.ok) throw new Error(response.statusText);
    return response.json();
  })
  .then(data => console.log(data))
  .catch(err => console.error(err));

// 使用 async/await(推荐)
async function fetchData() {
  try {
    const response = await fetch('/api/data');
    if (!response.ok) throw new Error(response.statusText);
    const data = await response.json();
    console.log(data);
  } catch (err) {
    console.error(err);
  }
}

✅ 六、一句话总结

AJAX 通过 XMLHttpRequest 实现异步通信,提升用户体验。虽然原生实现复杂,但可通过 Promise 封装或使用 fetch API 简化开发。现代项目推荐使用 fetchaxios 等库。


💡 进阶建议

  • 使用 async/await 替代 .then(),代码更清晰;
  • 添加请求超时机制;
  • 统一错误处理(如拦截器);
  • 使用 AbortController 实现请求取消;
  • 考虑使用 axiosky 等第三方库,功能更强大;
  • 注意跨域问题(CORS);
  • 对敏感数据进行加密传输;