AJAX原理与XMLHttpRequest

目录

一、XMLHttpRequest使用步骤

基本语法

步骤 1:创建 XHR 对象

步骤 2:调用 open() 方法

步骤 3:监听 loadend 事件

步骤 4:调用 send() 方法

二、完整示例

1. GET 请求(带查询参数)

2. POST 请求(提交 JSON 数据)

三、关键注意事项

四、URLSearchParams

1. URLSearchParams 的作用

2. 代码示例解析

3. URLSearchParams 常用方法

1. 添加参数

2. 删除参数

3. 获取参数值

4. 遍历参数

4. 处理特殊字符

5. 可选链操作符

 五、简易封装axios

1. Axios 核心设计

2. 简易封装示例

3. AJAX 与 Axios 对比


AJAX(Asynchronous JavaScript and XML)核心原理:通过浏览器提供的 XMLHttpRequest(XHR)对象,实现异步通信,无需刷新页面即可与服务器交换数据。

一、XMLHttpRequest使用步骤

基本语法

  • 创建对象 → 配置请求 → 监听事件 → 发送请求 
const xhr = new XMLHttpRequest()
xhr.open('请求方法', '请求url网址')
xhr.addEventListener('loadend', () => {// 响应结果console.log(xhr.response)
})
xhr.send()

步骤 1:创建 XHR 对象

const xhr = new XMLHttpRequest();
  • 作用:初始化一个 XHR 实例,用于后续的请求配置和操作。

  • 注意:旧版 IE(< IE7)需使用 ActiveXObject,但现代浏览器无需兼容处理。


步骤 2:调用 open() 方法

xhr.open(method, url, async);
  • 参数说明

    • method:HTTP 方法(GETPOSTPUT 等)。

    • url:请求的目标地址(支持绝对或相对路径)。

    • async:是否异步(默认为 true,强烈建议使用异步)。

  • 关键点

    • GET 请求的查询参数需直接拼接到 URL 中(需手动编码)。

      const params = { page: 1, keyword: 'AJAX' };
      const query = new URLSearchParams(params).toString(); // 自动编码
      const url = `https://api.example.com/data?${query}`;
      xhr.open('GET', url, true);
    • POST 请求的数据在 send() 中传递(需配合请求头)。


步骤 3:监听 loadend 事件

xhr.addEventListener('loadend', function() {// 请求完成(无论成功或失败)if (xhr.status >= 200 && xhr.status < 300) {console.log('成功:', xhr.responseText);} else {console.error('失败:', xhr.status, xhr.statusText);}
});
  • loadend 事件特性

    • 在请求完成(包括成功、失败或取消)后触发。

    • 替代传统 onreadystatechange 的繁琐状态判断。

  • 响应数据获取

    • xhr.responseText:字符串形式的响应数据(如 JSON、HTML)。

    • xhr.response:根据 responseType 自动转换后的数据(如 JSON 对象)。


步骤 4:调用 send() 方法

xhr.send(body);
  • GET 请求send() 无参数或传 null

    xhr.send();
  • POST 请求:传递请求体数据(需设置 Content-Type)。

    // 设置请求头(JSON 格式)
    xhr.setRequestHeader('Content-Type', 'application/json');// 提交 JSON 数据
    const postData = JSON.stringify({ username: 'john', age: 25 });
    xhr.send(postData);// 提交 FormData(文件上传)
    const formData = new FormData();
    formData.append('file', fileInput.files[0]);
    xhr.send(formData);

二、完整示例

1. GET 请求(带查询参数)

const xhr = new XMLHttpRequest();// 构建带查询参数的 URL
const params = { page: 1, search: 'AJAX 教程' };
const url = `https://api.example.com/data?${new URLSearchParams(params)}`;xhr.open('GET', url, true);xhr.addEventListener('loadend', () => {if (xhr.status === 200) {const data = JSON.parse(xhr.responseText);console.log('数据:', data);} else {console.error(`请求失败: ${xhr.status}`);}
});xhr.send();

2. POST 请求(提交 JSON 数据)

const xhr = new XMLHttpRequest();
xhr.open('POST', 'https://api.example.com/submit', true);// 设置请求头
xhr.setRequestHeader('Content-Type', 'application/json');xhr.addEventListener('loadend', () => {if (xhr.status === 201) {console.log('提交成功:', xhr.responseText);} else {console.error(`错误: ${xhr.status}`);}
});// 提交 JSON 数据
const data = { title: 'XHR 教程', content: '详细指南' };
xhr.send(JSON.stringify(data));

三、关键注意事项

  1. 查询参数编码

    // 手动编码示例
    const keyword = '前端&后端';
    const encodedKeyword = encodeURIComponent(keyword); // → '前端%26后端'
    • 使用 URLSearchParams 或 encodeURIComponent 避免特殊字符问题。

  2. POST 请求头设置

    • 必须根据数据类型设置 Content-Type,否则服务器无法正确解析。

      • application/json:JSON 数据。

      • multipart/form-data:文件上传。

      • application/x-www-form-urlencoded:表单数据。

  3. 错误处理

    • 结合 loadend 和 xhr.status 处理 HTTP 状态码。

    • 监听 error 和 timeout 事件处理网络错误和超时。

      xhr.addEventListener('error', () => {console.error('网络错误');
      });xhr.timeout = 5000; // 设置超时时间
      xhr.addEventListener('timeout', () => {console.error('请求超时');
      });
  4. 同步请求已废弃

    • open() 的第三个参数若设为 false(同步请求),会导致页面阻塞,现代开发中禁止使用。

XHR和Axios的默认请求头对比

场景XHR(原生)Axios
发送 JSON 数据需手动设置 Content-Type自动设置 Content-Type: application/json
发送 FormData自动设置 multipart/form-data自动设置 multipart/form-data
全局默认头支持通过 axios.defaults.headers 配置全局头
拦截器支持请求/响应拦截器统一管理头

必须声明Headers的情况

场景XHRAxios
发送非表单数据必须手动设置 Content-Type自动处理,可手动覆盖
身份认证必须设置 Authorization必须设置 Authorization
跨域自定义头必须声明且服务器允许必须声明且服务器允许
文件上传使用 FormData 时自动处理使用 FormData 时自动处理

四、URLSearchParams

1. URLSearchParams 的作用

URLSearchParams 是一个 Web API,用于解析、操作 URL 的查询参数(即 ? 后的部分)。它可以:

  1. 将对象转换为 URL 查询字符串(自动编码特殊字符)。

  2. 解析现有查询字符串为键值对。

  3. 动态添加、删除、遍历参数


2. 代码示例解析

qObj = { key1: 'value1', key2: 'value2' }
const paramsObj = new URLSearchParams(qObj);
const queryString = paramsObj.toString();
xhr.open('GET', `http://example.net/api?${queryString}`);

步骤分解:

  1. 创建 URLSearchParams 实例

    const paramsObj = new URLSearchParams(qObj);
    • 假设 qObj 是一个对象(如 { key1: 'value1', key2: 'value2' })。

    • URLSearchParams 会将其转换为键值对结构。

  2. 生成查询字符串

    const queryString = paramsObj.toString();
    • toString() 方法将参数转换为标准的 URL 查询字符串(如 key1=value1&key2=value2)。

    • 自动处理编码:空格转为 %20,中文转为 %E4%B8%AD 等。

  3. 拼接完整 URL

    xhr.open('GET', `http://example.net/api?${queryString}`);
    • 最终生成的 URL 示例:
      http://example.net/api?key1=value1&key2=value2


3. URLSearchParams 常用方法

1. 添加参数
paramsObj.append('page', 1); // 添加新参数
paramsObj.append('page', 2); // 允许重复键:page=1&page=2
2. 删除参数
paramsObj.delete('key1'); // 删除指定键
3. 获取参数值
const value = paramsObj.get('key1'); // 获取第一个值
const allValues = paramsObj.getAll('page'); // 获取所有值(数组)
4. 遍历参数
for (const [key, value] of paramsObj) {console.log(key, value);
}

4. 处理特殊字符

URLSearchParams 会自动编码特殊字符,无需手动调用 encodeURIComponent
示例:

const params = new URLSearchParams({ city: '北京', q: 'a&b=c' });
console.log(params.toString()); 
// 输出:city=%E5%8C%97%E4%BA%AC&q=a%26b%3Dc

5. 可选链操作符

JavaScript 中的 ?. 是可选链操作符(Optional Chaining Operator),用于安全地访问对象的深层属性。它的作用是:当某个中间属性为 null 或 undefined 时,直接返回 undefined,而不会抛出错误。


代码示例分析:

// 假设 xhr 是 XMLHttpRequest 的实例
const data = xhr.response?.data;
  1. xhr.response
    XHR 请求完成后,xhr.response 是服务器返回的数据。
    如果请求未完成或失败,xhr.response 可能是 null 或 undefined

  2. xhr.response?.data

    • 如果 xhr.response 存在:继续访问 data 属性。

    • 如果 xhr.response 是 null 或 undefined:直接返回 undefined,不会尝试访问 .data

可选链操作符(?.)的核心规则:

场景代码示例结果
属性存在obj?.prop返回 obj.prop
属性不存在(null/undefinedobj?.prop返回 undefined不会报错
深层属性访问obj?.prop1?.prop2逐层检查,任一中间属性为 null/undefined 则返回 undefined
函数调用obj.method?.()如果 obj.method 存在则调用,否则返回 undefined

 五、简易封装axios

Axios 原理:基于 Promise 封装的 HTTP 客户端库,底层依赖 XMLHttpRequest(浏览器)或 http 模块(Node.js),提供更简洁、强大的 API。

1. Axios 核心设计

  1. 适配器模式

    • 浏览器环境:使用 XMLHttpRequest 发送请求。

    • Node.js 环境:使用 http 模块发送请求。

    • 统一 API:开发者无需关注底层差异。

  2. 拦截器机制

    • 请求拦截器:在请求发送前统一处理(如添加 Token)。

    • 响应拦截器:在响应返回后统一处理(如错误过滤)。

    // 添加请求拦截器
    axios.interceptors.request.use(config => {config.headers.Authorization = 'Bearer token';return config;
    });// 添加响应拦截器
    axios.interceptors.response.use(response => response.data, // 提取 data 字段error => Promise.reject(error)
    );
  3. 配置合并策略

    • 全局配置 → 实例配置 → 单次请求配置,优先级递增。

    • 自动处理 headers(如 Content-Type 根据数据类型推断)。

  4. Promise 链式调用

    • 所有请求返回 Promise 对象,支持 async/await

    • 错误通过 .catch() 或 try/catch 统一处理。

2. 简易封装示例

模拟 axios 函数封装,更深入了解 axios 内部运作原理:

//定义myAxios函数,接收配置对象,返回Promise对象
function myAxios(config) {return new Promise((resolve, reject) => {const xhr = new XMLHttpRequest()//判断有params选项,携带查询参数if (config.params) {//使用URLSearchParams转换,并携带到url上const paramsObj = new URLSearchParams(config.params)const queryString = paramsObj.toString()config.url += `?${queryString}`}//发起XHR请求,默认请求方法为GETxhr.open(config.method || 'GET', config.url)xhr.addEventListener('loadend', () => {//调用成功/失败的处理程序if (xhr.status >= 200 && xhr.status < 300) {resolve(JSON.parse(xhr.response))}else {reject(new Error(xhr.response))}})//判断有data选项,携带请求体if (config.data) {xhr.setRequestHeader('Content-Type', 'application/json')xhr.send(JSON.stringify(config.data))}else {xhr.send()}})
}

3. AJAX 与 Axios 对比

特性AJAX(原生 XHR)Axios
底层实现直接操作 XMLHttpRequest 对象封装 XHR 或 Node.js http 模块,提供统一 API
异步处理回调函数基于 Promise,支持 async/await
数据转换手动解析 JSON、XML 等格式自动转换 JSON 数据
拦截器需手动实现内置请求/响应拦截器
取消请求使用 xhr.abort()支持 CancelToken 和 AbortController
跨域处理需服务端配合 CORS 或 JSONP自动处理 CORS,支持 withCredentials 配置
代码简洁性冗余,需手动处理细节链式调用,配置化 API

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/76767.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python写个0~12个月宝宝喂养规划表

下载字体&#xff1a;https://github.com/adobe-fonts/source-han-sans/releases 下载fpdf2 pip uninstall fpdf pip install fpdf2运行代码 ​from fpdf import FPDF from fpdf.enums import XPos, YPos# 创建 PDF 类 class BabyFeedingPDF(FPDF):def header(self):self.s…

集中趋势描述

一、集中趋势的定义与核心目标 集中趋势指数据向其中心值聚集的倾向,反映数据的典型水平或分布中心。其核心是通过统计指标(如众数、中位数、均值)概括数据的核心特征,帮助快速理解数据分布的核心位置。 核心作用:简化复杂数据、指导业务决策(如确定用户平均消费水平)、…

【NLP】Attention机制

1.模型对比 RNN(马尔科夫链式编码) 通过递归计算逐个处理 token,当前编码结果 h t h_t ht​仅依赖前一步的隐藏状态 h t − 1 h_{t-1} ht−1​和当前输入 x t x_t xt​局限性:序列建模需严格串行,无法并行;长距离依赖易丢失(梯度消失/爆炸)例:双向 LSTM 需正向+反向两…

基于OpenCV与PyTorch的智能相册分类器全栈实现教程

引言&#xff1a;为什么需要智能相册分类器&#xff1f; 在数字影像爆炸的时代&#xff0c;每个人的相册都存储着数千张未整理的照片。手动分类不仅耗时&#xff0c;还容易遗漏重要瞬间。本文将手把手教你构建一个基于深度学习的智能相册分类系统&#xff0c;实现&#xff1a;…

活动安排问题 之 前缀和与差分

文章目录 D. Robert Hood and Mrs Hood 考虑到一个活动开始时间和结束时间s,e&#xff0c;那么可以影响到的范围就是 s-d1,e,所以我们只需对这个每一个活动可以影响到的区域进行标记即可&#xff0c;当然为了降低时间复杂度&#xff0c;我们将使用前缀和与差分 t int(input()…

C++之 多继承

在学校里有老师和学生&#xff0c;他们都是人&#xff0c;我么应该创建一个名为 Person 的基类和两个名为 Teacher 和Student 的子类&#xff0c;后两者是从前者继承来的 有一部分学生还教课挣钱&#xff08;助教&#xff09;&#xff0c;也就是同时存在着两个”是一个”关系&…

大数据学习栈记——Redis安装及其使用

本文介绍NoSQL技术&#xff1a;Redis的安装及其使用。操作系统&#xff1a;Ubuntu24.04 Redis介绍 Redis是一个键值&#xff08;key-value&#xff09;存储系统&#xff0c;即键值对非关系型数据库&#xff0c;和Memcached类似&#xff0c;目前正在被越来越多的互联网公司采用…

2024团体程序设计天梯赛L3-1 夺宝大赛

L3-037 夺宝大赛 分数 30 作者 陈越 单位 浙江大学 夺宝大赛的地图是一个由 nm 个方格子组成的长方形&#xff0c;主办方在地图上标明了所有障碍、以及大本营宝藏的位置。参赛的队伍一开始被随机投放在地图的各个方格里&#xff0c;同时开始向大本营进发。所有参赛队从一个方格…

JMeter的高并发和高频率和分布式

性能测试 模拟各种正常的、峰值的测试环境&#xff0c;检测程序的各项性能指标是否能够达标 高并发 JMeter中内置了定时器&#xff0c;可以实现时间模式相关的性能测试 需求1:同一时刻100个同学去访问学生管理系统的查询所有学院信息功能&#xff0c;统计高并发情况下平均响…

ubuntu学习day2

linux常用命令 3.文件查看及处理命令 3.1查看文件内容 cat[选项][文件] -b 对非空输出行编号 -E 在每行结束处显示$ -n 对输出的所有行编号 -s 不输出多行空行 标准输入、标准输出和标准错误 在 Linux 中&#xff0c;每个进程默认有三个文件描述符&#xff1a; 标准输入&…

项目中引入 Redis 及 常用五种数据类型

在平常的开发过程中&#xff0c;我们经常会用到缓存的技术。比如&#xff0c;验证码60秒后过期、计数器的实现、商品信息存储在缓存中快速展示等。那么&#xff0c;项目中经常会使用到的便是 redis 缓存。redis 在内存中操作&#xff0c;读写快。Redis 常用的数据类型有五种&am…

Spark-SQL简介及核心编程

Spark-SQL概述&#xff1a;是Spark用于结构化数据处理的模块&#xff0c;前身是Shark。Shark基于Hive开发&#xff0c;使SQL-on-Hadoop性能大幅提升&#xff0c;但对Hive依赖制约了Spark发展。SparkSQL汲取Shark优点并重新开发&#xff0c;在数据兼容、性能优化和组件扩展上优势…

奇趣点播系统测试报告

1.项目简介 本项目旨在搭建一个视频共享点播系统&#xff0c;服务器支持用户通过前端浏览器访问服务器&#xff0c;获取展示与观看和操作的界面&#xff0c;最终实现视频的上传以及观看和删改查等基础管理功能。让用户拥有良好的观看体验和分享视频的快捷方式&#xff0c;此外…

【Web API系列】WebSocketStream API 深度实践:构建高吞吐量实时应用的流式通信方案

前言 在当今的 Web 开发领域&#xff0c;实时通信已成为许多应用的核心需求。无论是即时聊天、实时数据仪表盘&#xff0c;还是在线游戏和金融交易系统&#xff0c;都需要高效的双向数据传输能力。传统的 WebSocket API 为此提供了基础支持&#xff0c;但在处理大规模数据流、…

基于LangGraph的智能报告生成平台项目分析

前言 不知道你是否知道或者了解OpenAI and Gemini Deep Research。他们是一种能够根据输入问题进行规划、结合网络搜索获取信息并最终呈现结果的研究工具或技术。那这样research是如何实现的呢?最近刚好看到一个实现类似功能的开源项目: open_deep_search。本文将基于该项目进…

Redis 常见的集群架构

Redis 常见的集群架构 以下是 Redis 常见的集群架构及其核心模式详解&#xff0c;结合其设计原理、适用场景和优缺点进行综合说明&#xff1a; 一、主从复制模式 架构原理 角色划分&#xff1a;包含一个主节点&#xff08;Master&#xff09;和多个从节点&#xff08;Slave&…

面试宝典(C++基础)-01

文章目录 1. C++基础1.1 C++特点1.2 说说C语言和C++的区别1.3 说说 C++中 struct 和 class 的区别1.4 include头文件的顺序以及双引号""和尖括号<>的区别1.5 说说C++结构体和C结构体的区别1.6 导入C函数的关键字是什么,C++编译时和C有什么不同?1.7 C++从代码…

快速获得ecovadis认证的方法,如何提升ecovadis认证分数,有效期是多久

快速获得EcoVadis认证的方法 EcoVadis认证是企业社会责任&#xff08;CSR&#xff09;和可持续发展能力的国际评估标准&#xff0c;被广泛应用于供应链管理&#xff08;如苹果、微软、联合利华等巨头要求供应商通过EcoVadis评估&#xff09;。以下是快速获得认证的关键步骤&am…

ubuntu 安装samba

ubuntu 版本&#xff1a;Ubuntu 24.04.2 LTS 1. 保证连网 2. 安装samba sudo apt install samba 在安装结束以后&#xff0c;我们可以使用下面的命令来查看安装&#xff1a; apt list | grep samba freeipa-client-samba/noble 4.11.1-2 amd64 ldb-tools/noble 2:2.8.0samba…

基于SpringBoot的宠物健康咨询系统(源码+数据库+万字文档)

502基于SpringBoot的宠物健康咨询系统&#xff0c;系统包含三种角色&#xff1a;管理员、用户&#xff0c;顾问主要功能如下。 【用户功能】 1. 首页&#xff1a;查看系统主要信息和最新动态。 2. 公告&#xff1a;浏览系统发布的公告信息。 3. 顾问&#xff1a;浏览可提供咨询…