【AJAX-Day1】HTTP协议与XHR基础
🎯 核心目标:理解 AJAX 是什么、HTTP 请求/响应结构、使用原生 XHR 发送请求、掌握 Axios 基本用法
一、AJAX 概述
1.1 什么是 AJAX?
AJAX(Asynchronous JavaScript And XML)是一种无需刷新页面就能与服务器交换数据并更新部分页面的技术。
传统网页交互:
用户操作 → 整页提交 → 服务器响应 → 整页刷新(体验差)
AJAX 交互:
用户操作 → 后台异步请求 → 服务器响应 → 局部更新页面(体验好)
AJAX 能做什么:
- 搜索框实时联想(百度、淘宝)
- 下拉刷新 / 上拉加载更多
- 表单提交不刷新页面
- 实时聊天消息
- 地图数据动态加载
1.2 客户端与服务端
客户端(Client) ←→ 服务端(Server)
浏览器、App 发请求 Node.js、Java、PHP、Python...
收响应 提供数据、处理业务逻辑
URL 格式:
https://www.example.com:8080/api/users?page=1&size=10#section
↑ ↑ ↑ ↑ ↑ ↑
协议 域名/IP 端口 路径 查询参数 锚点
二、HTTP 协议
2.1 什么是 HTTP?
HTTP(HyperText Transfer Protocol)是客户端和服务端之间数据传输的规则,规定了请求和响应的格式。
2.2 HTTP 请求报文
请求行: GET /api/users?page=1 HTTP/1.1
请求头: Host: api.example.com
Content-Type: application/json
Authorization: Bearer eyJhbG...
Accept: application/json
空行: (必须有,分隔请求头和请求体)
请求体: {"name":"张三","age":18} ← GET 请求没有请求体
请求方法(HTTP Verbs):
| 方法 | 语义 | 有请求体 | 常见用途 |
|---|---|---|---|
| GET | 获取资源 | ❌ | 查询列表、详情 |
| POST | 新建资源 | ✅ | 提交表单、上传 |
| PUT | 完整更新 | ✅ | 更新整个资源 |
| PATCH | 部分更新 | ✅ | 修改某个字段 |
| DELETE | 删除资源 | ❌ | 删除操作 |
2.3 HTTP 响应报文
状态行: HTTP/1.1 200 OK
响应头: Content-Type: application/json; charset=utf-8
Content-Length: 256
Date: Mon, 06 Apr 2026 12:00:00 GMT
空行:
响应体: {"code":200,"data":[...],"message":"success"}
常见状态码:
| 状态码 | 含义 | 说明 |
|---|---|---|
| 200 | OK | 请求成功 |
| 201 | Created | 资源创建成功 |
| 301 | Moved Permanently | 永久重定向 |
| 302 | Found | 临时重定向 |
| 304 | Not Modified | 缓存未过期,用本地缓存 |
| 400 | Bad Request | 请求参数有误 |
| 401 | Unauthorized | 未登录/Token失效 |
| 403 | Forbidden | 无权限 |
| 404 | Not Found | 资源不存在 |
| 405 | Method Not Allowed | 请求方法不允许 |
| 500 | Internal Server Error | 服务器内部错误 |
| 502 | Bad Gateway | 网关错误(通常是服务挂了) |
2.4 请求头常见字段
Content-Type: application/json → 请求体是 JSON
Content-Type: application/x-www-form-urlencoded → 表单数据(key=val&key=val)
Content-Type: multipart/form-data → 文件上传
Authorization: Bearer <token> → 携带身份令牌
Accept: application/json → 告诉服务器我能接受的格式
Accept-Language: zh-CN,zh;q=0.9 → 语言偏好
Cache-Control: no-cache → 不使用缓存
三、原生 XMLHttpRequest(XHR)
3.1 基本使用
// 1. 创建 XHR 对象
const xhr = new XMLHttpRequest()
// 2. 配置请求(方法、URL、是否异步)
xhr.open('GET', 'https://api.example.com/users')
// 3. 监听状态变化
xhr.addEventListener('loadend', () => {
// xhr.status:HTTP 状态码
// xhr.response:响应体(字符串)
if (xhr.status === 200) {
const data = JSON.parse(xhr.response)
console.log(data)
} else {
console.error('请求失败:', xhr.status)
}
})
// 4. 发送请求
xhr.send()
3.2 readyState 状态值
0 - UNSENT:XHR 对象已创建,但未调用 open()
1 - OPENED:open() 已调用
2 - HEADERS_RECEIVED:send() 已调用,响应头已收到
3 - LOADING:响应体正在接收中
4 - DONE:响应完整接收完毕
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(JSON.parse(xhr.responseText))
}
}
💡 推荐用
loadend事件替代readystatechange,更简洁。
3.3 GET 请求 —— 携带查询参数
// 参数拼接在 URL 后面
const params = new URLSearchParams({
page: 1,
size: 10,
keyword: '张三'
})
const url = `https://api.example.com/users?${params}`
// → https://api.example.com/users?page=1&size=10&keyword=%E5%BC%A0%E4%B8%89
xhr.open('GET', url)
xhr.send() // GET 请求 send() 不传参数
3.4 POST 请求 —— 携带请求体
const xhr = new XMLHttpRequest()
xhr.open('POST', 'https://api.example.com/users')
// 必须设置 Content-Type!
xhr.setRequestHeader('Content-Type', 'application/json')
xhr.addEventListener('loadend', () => {
if (xhr.status === 201) {
console.log('创建成功:', JSON.parse(xhr.response))
}
})
// send() 中传递请求体(必须序列化为字符串)
xhr.send(JSON.stringify({
name: '张三',
age: 18,
email: 'zhangsan@example.com'
}))
3.5 XHR 封装(Promise 化)
function request(method, url, data = null) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open(method, url)
xhr.setRequestHeader('Content-Type', 'application/json')
xhr.addEventListener('loadend', () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(JSON.parse(xhr.response))
} else {
reject(new Error(`HTTP Error: ${xhr.status}`))
}
})
xhr.addEventListener('error', () => {
reject(new Error('Network Error'))
})
xhr.send(data ? JSON.stringify(data) : null)
})
}
// 使用
request('GET', '/api/users')
.then(data => console.log(data))
.catch(err => console.error(err))
四、Axios 基础
4.1 为什么用 Axios?
原生 XHR 代码繁琐,Axios 是基于 XHR 的封装库,提供更简洁的 API:
- 自动 JSON 序列化/反序列化
- Promise-based API
- 拦截器机制
- 请求取消
- 请求/响应转换
4.2 引入 Axios
<!-- CDN 引入(学习时用) -->
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<!-- npm 安装(项目中用) -->
<!-- npm install axios -->
<!-- import axios from 'axios' -->
4.3 基本使用
// GET 请求
axios({
method: 'GET',
url: 'https://api.example.com/users',
params: { page: 1, size: 10 } // 查询参数(自动拼到URL)
}).then(result => {
// result.data:响应体数据(axios 已自动 JSON 解析)
// result.status:HTTP 状态码
// result.headers:响应头
console.log(result.data)
})
// POST 请求
axios({
method: 'POST',
url: 'https://api.example.com/users',
data: { name: '张三', age: 18 } // 请求体(自动 JSON 序列化)
}).then(result => {
console.log(result.data)
})
4.4 快捷方法
// GET
axios.get('/api/users', { params: { page: 1 } })
// POST
axios.post('/api/users', { name: '张三', age: 18 })
// PUT
axios.put('/api/users/1', { name: '李四' })
// DELETE
axios.delete('/api/users/1')
// PATCH
axios.patch('/api/users/1', { age: 20 })
4.5 async/await 写法(推荐)
async function getUsers() {
try {
const { data } = await axios.get('/api/users', {
params: { page: 1, size: 10 }
})
console.log(data)
return data
} catch (error) {
if (error.response) {
// 服务器响应了,但状态码不在 2xx 范围
console.error('状态码:', error.response.status)
console.error('错误信息:', error.response.data)
} else if (error.request) {
// 请求发出去了,但没有收到响应(网络问题)
console.error('网络错误')
} else {
console.error('请求配置错误:', error.message)
}
}
}
五、综合练习
练习:图书管理系统(增删改查)
const BASE_URL = 'http://ajax-base-api-t.itheima.net'
// 获取图书列表
async function getBooks() {
const { data } = await axios.get(`${BASE_URL}/api/books`)
return data.data
}
// 新增图书
async function addBook(bookName) {
const { data } = await axios.post(`${BASE_URL}/api/books`, {
bookname: bookName
})
return data
}
// 删除图书
async function deleteBook(id) {
const { data } = await axios.delete(`${BASE_URL}/api/books/${id}`)
return data
}
// 更新图书
async function updateBook(id, bookName) {
const { data } = await axios.put(`${BASE_URL}/api/books/${id}`, {
bookname: bookName
})
return data
}
六、知识图谱
HTTP协议与XHR基础
├── AJAX
│ ├── 定义:异步JS与XML,局部刷新页面
│ └── 场景:搜索联想、分页加载、表单提交
├── HTTP 协议
│ ├── 请求报文:请求行/头/体(方法 + URL + 参数)
│ ├── 响应报文:状态行/头/体(状态码 + 数据)
│ ├── 请求方法:GET/POST/PUT/PATCH/DELETE
│ └── 状态码:200/201/301/304/400/401/403/404/500
├── XHR(XMLHttpRequest)
│ ├── open() → send() → loadend 事件
│ ├── GET:参数拼 URL(URLSearchParams)
│ ├── POST:setRequestHeader + send(JSON)
│ └── Promise 封装
└── Axios
├── 引入:CDN / npm
├── 配置对象:method/url/params/data
├── 快捷方法:get/post/put/delete/patch
└── async/await + try/catch(推荐)
七、高频面试题
Q1:GET 和 POST 的区别?
① GET 参数在 URL(有长度限制),POST 在请求体(无限制);② GET 是幂等的(多次请求结果相同),POST 不是;③ GET 有缓存,POST 不缓存;④ GET 用于获取数据,POST 用于提交/创建数据。
Q2:HTTP 状态码 301 和 302 的区别?
都是重定向,但 301 是永久重定向(浏览器/搜索引擎会记住新地址),302 是临时重定向(每次仍发到原地址)。SEO 场景中 301 更常用。
Q3:AJAX 请求为什么是异步的?
因为网络请求耗时不确定,如果同步等待会阻塞 JS 线程(UI 卡死)。通过事件循环机制,AJAX 请求被放到 Web APIs 中执行,完成后回调函数进入宏任务队列,不影响主线程。
➡️ 下一篇:Day2 - Promise与回调地狱