用 promise 封装 xmlhttprequest 的核心是通过 resolve/reject 转换成功/失败状态,使 ajax 支持 .then()/.catch() 链式调用;需校验 status、设置 responsetype、统一错误 reject,并可扩展 get/post 快捷方法及 ie 兼容层。

用 Promise 封装传统回调型 Ajax 请求,核心是把 XMLHttpRequest 的成功/失败逻辑,通过 resolve 和 reject 转成 Promise 的状态流转,让异步调用能用 .then() 和 .catch() 处理,更简洁、可链式、易错误捕获。
封装基础 XMLHttpRequest + Promise
手动创建 XMLHttpRequest 实例,监听 onload 和 onerror,在对应时机调用 resolve 或 reject:
-
成功时:检查
xhr.status是否在 200–299 范围,是则resolve(xhr.response) -
失败时:包括网络错误、超时、状态码异常(如 404/500),统一
reject(new Error(...)) - 记得设置
xhr.responseType(如'json'),避免手动JSON.parse
示例代码:
function ajax(url, options = {}) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open(options.method || 'GET', url);
// 自动处理 JSON 响应
if (options.headers?.['Content-Type'] === 'application/json' ||
options.responseType === 'json') {
xhr.responseType = 'json';
}
xhr.onload = () => {
if (xhr.status >= 200 && xhr.status reject(new Error('Network error'));
xhr.ontimeout = () => reject(new Error('Request timeout'));
if (options.timeout) xhr.timeout = options.timeout;
// 设置请求头
Object.keys(options.headers || {}).forEach(key => {
xhr.setRequestHeader(key, options.headers[key]);
});
// 发送请求(有 body 才传)
const body = options.body ? JSON.stringify(options.body) : null;
xhr.send(body);
});
}
支持 GET/POST 等常用方法的快捷封装
为常用场景提供语义化函数,内部仍复用同一个 Promise 包装逻辑:
-
get(url):默认发 GET,自动加?t=时间戳防缓存(可选) -
post(url, data):自动设Content-Type: application/json,序列化 body - 所有函数返回 Promise,可直接
.then(data => ...).catch(err => ...)
例如:
const get = (url, options = {}) => ajax(url + (options.nocache ? `?t=${Date.now()}` : ''), {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
...options
});
const post = (url, data, options = {}) => ajax(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: data,
...options
});
// 使用
get('/api/user/1')
.then(user => console.log(user))
.catch(err => console.error(err));
post('/api/login', { username: 'a', password: 'b' })
.then(res => console.log('登录成功'))
.catch(err => alert('登录失败:' + err.message));
兼容旧版 IE?注意 XMLHttpRequest 版本差异
IE6–8 不支持原生 XMLHttpRequest,需降级用 ActiveXObject("Microsoft.XMLHTTP"):
- 判断是否存在
window.XMLHttpRequest,不存在则尝试 ActiveXObject - IE7–8 支持
onreadystatechange,需监听readyState === 4再检查 status - 不推荐为老 IE 做深度兼容;若必须支持,可在封装函数开头加兼容层
进阶:用 fetch 替代 XMLHttpRequest(现代推荐)
虽然问题聚焦于封装回调型 Ajax,但值得提一句:fetch 本身就是基于 Promise 的,无需手动封装:
- 语法更简洁:
fetch(url).then(r => r.json()).then(data => ...) - 注意:
fetch只在网络错误时 reject,4xx/5xx 仍 resolve,需手动检查response.ok - 如需 AbortController、上传进度等高级能力,
fetch+AbortSignal更现代、灵活
不复杂但容易忽略:Promise 封装的关键不是“写出来”,而是统一错误出口、明确成功条件、避免未 catch 的 rejected promise。做好这三点,回调地狱就真正解开了。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











