之前写过原生AJAX XH1封装,今天进行AJAX XH2进行封装升级,看看就行,实际开发过程中很少使用Ajax发送请求了。
你是不是还在写繁琐的onreadystatechange?文件上传没进度条、请求超时没提示、跨域带Cookie一脸懵?
别慌!XHR Level2直接把原生AJAX拉满战力。
一、先搞懂:XHR2到底强在哪?
老版AJAX(XHR1)就是个老年机:只能发普通请求、没进度、没超时、传文件费劲。
XHR2直接升级成旗舰智能机:
二、通用XHR2 AJAX封装函数
/**
* XHR Level2 升级版AJAX封装 通用Ajax请求封装函数
* 支持:GET/POST/PUT/DELETE + 三种POST编码 + 进度/超时/跨域
* @param {Object} options - 配置对象
* @param {string} options.url - 请求地址【必填】
* @param {string} [options.method='GET'] - 请求方式,默认GET
* @param {Object} [options.params] - URL查询参数
* @param {Object|FormData} [options.data] - 请求体参数
* @param {Function} [options.onSuccess] - 成功回调
* @param {Function} [options.onError] - 失败回调
* @param {number} [options.timeout=10000] - 超时时间,默认10秒
* @param {Function} [options.onProgress] - 下载进度回调
* @param {Function} [options.onUploadProgress] - 上传进度回调(文件上传用)
* @param {boolean} [options.withCredentials=false] - 跨域是否带Cookie
*/
function ajax(options) {
// 1. 必传参数校验:没有url直接报错
if (!options.url) thrownewError("宝贝,请求地址url不能为空哦!");
// 2. 默认参数兜底,不传就用默认值
const {
url,
method = "GET",
params = {},
data = null,
onSuccess = () => {},
onError = () => {},
// XHR2 进阶配置(自动兼容,不用手动传)
timeout = 10000,
onProgress = () => {},
onUploadProgress = () => {},
withCredentials = false
} = options;
// 3. 创建XHR对象
const xhr = new XMLHttpRequest();
// 4. 处理URL查询参数(params自动拼接到地址栏)
let queryStr = new URLSearchParams(params).toString();
const requestUrl = queryStr ? `${url}?${queryStr}` : url;
const reqMethod = method.toUpperCase();
// 5. 初始化请求
xhr.open(reqMethod, requestUrl, true);
// 6. XHR2 核心配置
xhr.timeout = timeout; // 超时时间
xhr.withCredentials = withCredentials; // 跨域带Cookie
xhr.responseType = "json"; // 自动解析JSON
// 7. 【关键】POST请求自动设置请求头(三种编码格式)
const setPostHeader = () => {
// 情况1:数据是 FormData(文件上传专用)
if (data instanceof FormData) {
// FormData:浏览器自动设置 multipart/form-data,不用手动写!
return;
}
// 情况2:数据是普通对象(不是null)
if (typeof data === "object" && data !== null) {
// JSON格式
xhr.setRequestHeader("Content-Type", "application/json;charset=utf-8");
} else {
// 情况3:其他情况(字符串、表单格式)
// application/x-www-form-urlencoded规则就是:key=value&key=value
// 比如:name=张三&age=18&sex=男
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
}
};
// 非GET请求设置请求头
if (reqMethod !== "GET")
setPostHeader();
// 8. 请求完成回调(XHR2新特性,替代readyState)
xhr.onload = () => {
try {
if (xhr.status >= 200 && xhr.status < 300) {
// XHR2 直接用 response,自动按 responseType 解析
onSuccess(xhr.response);
} else {
onError(newError(`请求失败,状态码:${xhr.status}`));
}
} catch (err) {
onError(err);
}
};
// 9. XHR2 下载进度监听
xhr.onprogress = (e) => {
if (e.lengthComputable)
onProgress(e.loaded, e.total);
};
// 10. XHR2 上传进度监听(文件上传必备!)
xhr.upload.onprogress = (e) => {
if (e.lengthComputable)
onUploadProgress(e.loaded, e.total);
};
// 11. 异常兜底:超时/网络错误/请求取消
xhr.ontimeout = () => onError(newError("请求超时!网络开小差啦~"));
xhr.onerror = () => onError(newError("网络异常!检查一下链接吧~"));
// 12. 发送请求
let sendData = null;
if (reqMethod !== "GET") {
sendData = data instanceof FormData
? data // FormData直接传
: typeof data === "object"
? JSON.stringify(data) // JSON对象转字符串
: new URLSearchParams(data).toString(); // 表单格式
}
xhr.send(sendData);
}
三、交互式HTML页面
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>XHR2 AJAX实战演示</title>
<style>
button{ margin: 10px; padding: 8px 16px; cursor: pointer; }
.progress{ margin: 10px; color: #409eff; }
</style>
</head>
<body>
<h2>XHR2 AJAX 实战演示</h2>
<!-- 四个功能按钮 -->
<button onclick="getDemo()">1. GET请求</button>
<button onclick="postForm()">2. POST表单(默认编码)</button>
<button onclick="postJson()">3. POST-JSON格式</button>
<button onclick="uploadFile()">4. 文件上传(带进度)</button>
<!-- 进度展示区(XHR2核心效果) -->
<div class="progress" id="progress"></div>
<div class="progress" id="uploadProgress"></div>
<!-- 隐藏的文件上传框 -->
<input type="file" id="fileInput" style="display: none;">
<script>
// 把上面的 ajax() 封装函数粘贴到这里!
// 工具函数:更新进度文本
const showProgress = (loaded, total, elId, text) => {
const percent = ((loaded / total) * 100).toFixed(2);
document.getElementById(elId).innerText = `${text}:${percent}% (${loaded}/${total}字节)`;
};
// ==================== 4大实战案例 ====================
/**
* 1. GET请求演示(最常用,查数据)
*/
function getDemo() {
ajax({
url: "https://jsonplaceholder.typicode.com/todos/1",
params: { timestamp: Date.now() },
onSuccess: (res) => {
console.log("GET请求成功", res);
alert("GET请求成功!看控制台");
},
onError: (err) =>console.error("GET失败", err)
});
}
/**
* 2. POST表单请求(application/x-www-form-urlencoded)
* 场景:普通表单提交,兼容老服务器
*/
function postForm() {
ajax({
url: "https://jsonplaceholder.typicode.com/posts",
method: "POST",
data: { username: "前端小老弟", age: 20 },
onSuccess: (res) => {
console.log("表单POST成功", res);
alert("表单POST成功!");
},
onError: (err) =>console.error("表单POST失败", err)
});
}
/**
* 3. POST-JSON请求(application/json)
* 场景:现代接口最常用,传复杂对象
*/
function postJson() {
ajax({
url: "https://jsonplaceholder.typicode.com/posts",
method: "POST",
data: { user: "前端大神", info: { job: "开发", level: "高级" } },
onSuccess: (res) => {
console.log("JSON-POST成功", res);
alert("JSON-POST成功!");
},
onError: (err) =>console.error("JSON-POST失败", err)
});
}
/**
* 4. 文件上传(multipart/form-data + XHR2上传进度)
* 场景:头像上传、文件传输,封神级功能!
*/
function uploadFile() {
const fileInput = document.getElementById("fileInput");
fileInput.onchange = function () {
const file = fileInput.files[0];
if (!file) return;
// FormData:XHR2专属神器,自动处理文件编码
const formData = new FormData();
formData.append("file", file);
formData.append("filename", file.name);
ajax({
url: "https://jsonplaceholder.typicode.com/upload", // 替换为你的上传接口
method: "POST",
data: formData,
// 下载进度
onProgress: (loaded, total) => showProgress(loaded, total, "progress", "下载进度"),
// 上传进度(XHR2核心!看得见的进度条)
onUploadProgress: (loaded, total) => showProgress(loaded, total, "uploadProgress", "上传进度"),
onSuccess: (res) => {
console.log("文件上传成功", res);
alert("文件上传完成!");
},
onError: (err) =>console.error("上传失败", err)
});
};
fileInput.click();
}
</script>
</body>
</html>
四、解释分析
1. GET请求 —— 前端最常用的“白嫖党”
- params:自动拼接成
?key=value,干净卫生。
2. POST表单编码(application/x-www-form-urlencoded)
3. POST-JSON(application/json)
- 封装自动处理:对象自动转JSON字符串,自动设置请求头。
4. 文件上传(multipart/form-data)—— XHR2王牌功能
- 核心:
FormData + xhr.upload.onprogress。
为什么推荐XHR2?
- 代码极简:用
onload替代onreadystatechange,少写N行判断。 - 无依赖:不引jQuery、Axios,原生JS直接跑。
- 兼容性强:支持所有现代浏览器+IE10+,项目无忧。
五、总结
- 封装好的XHR2 AJAX函数直接复制,支持6大基础配置+全量XHR2特性。
- 4种请求方式全覆盖:GET、表单POST、JSON-POST、文件上传。
前端 requests 千万条,原生封装第一条!学会XHR2,告别繁琐AJAX,老板夸你效率高,产品看了都说好~
阅读原文:原文链接
该文章在 2026/3/23 12:01:20 编辑过