Promise 封装 AJAX 的核心是将 XMLHttpRequest 封装为标准 Promise,统一处理成功(resolve)与失败(reject),支持链式调用和 async/await;fetch 更推荐,原生基于 Promise,但需手动处理 4xx/5xx 状态码。

用 Promise 包装 AJAX 请求,核心是把 XMLHttpRequest 的异步流程封装成标准 Promise 对象,让请求逻辑更清晰、更易链式调用和错误处理。
手动封装 XMLHttpRequest 为 Promise
原生 XMLHttpRequest 回调嵌套深、状态判断繁琐。包装成 Promise 后,只需关注成功(resolve)和失败(reject)两种结果:
- 监听
onload:状态码在 200–299 范围时调用resolve(response) - 监听
onerror或检查status非法时调用reject(error) - 记得设置
responseType(如'json'),避免手动JSON.parse
示例:
function ajax(url, options = {}) {return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open(options.method || 'GET', url);
if (options.headers) {
Object.keys(options.headers).forEach(key => {
xhr.setRequestHeader(key, options.headers[key]);
});
}
xhr.responseType = options.responseType || 'json';
xhr.onload = () => {
if (xhr.status >= 200 && xhr.status resolve(xhr.response);
} else {
reject(new Error(`HTTP ${xhr.status}: ${xhr.statusText}`));
}
};
xhr.onerror = () => reject(new Error('Network error'));
xhr.send(options.body || null);
});
}
// 使用
ajax('/api/users')
.then(data => console.log(data))
.catch(err => console.error(err));
用 fetch 替代手动封装(推荐)
fetch 本身就是基于 Promise 的 API,无需额外包装,语义更清晰,且支持 async/await:
立即学习“Java免费学习笔记(深入)”;
- 注意:
fetch只在网络错误时 reject,4xx/5xx 状态码仍会 resolve,需手动判断response.ok - 响应体需显式调用
.json()、.text()等方法读取,它们也返回 Promise - 可搭配
AbortController实现请求取消
示例:
async function getUser() {try {
const res = await fetch('/api/users');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
return data;
} catch (err) {
console.error('请求失败:', err);
throw err;
}
}
封装通用请求函数(增强版)
实际项目中常进一步封装,统一处理鉴权、Loading、错误提示等:
- 自动携带 token(从 localStorage 或全局状态读取)
- 对非 2xx 响应统一抛出业务错误(如根据后端
{ code, message }字段) - 支持超时控制(用
AbortSignal.timeout()或 Promise.race)
示例(基于 fetch):
function request(url, options = {}) {const headers = {
'Content-Type': 'application/json',
...options.headers,
Authorization: `Bearer ${localStorage.getItem('token')}`
};
const config = {
method: options.method || 'GET',
headers,
signal: options.signal,
...options
};
if (config.method !== 'GET' && options.body) {
config.body = JSON.stringify(options.body);
}
return fetch(url, config)
.then(res => {
if (!res.ok) {
return res.json().then(err => Promise.reject(err));
}
return res.json();
});
}
与 async/await 配合使用更简洁
Promise 封装完成后,配合 async/await 写法更接近同步逻辑,利于阅读和调试:
- 多个请求可串行:
await req1(); await req2(); - 并行请求用
Promise.all([req1(), req2()]) - 错误统一用 try/catch 捕获,不用层层 .catch
示例:
async function loadUserProfile() {try {
const [user, posts] = await Promise.all([
request('/api/user'),
request('/api/posts')
]);
renderProfile({ user, posts });
} catch (err) {
showError(err.message || '加载失败');
}
}


















