原生 Ajax 请求实现
使用 XMLHttpRequest 和 Fetch API 实现 Ajax 请求
问题
在实际开发中,如何使用原生 JavaScript 实现 Ajax 请求?
解答
XMLHttpRequest 方式
function ajax(options) {
const { method = 'GET', url, data = null, headers = {} } = options;
return new Promise((resolve, reject) => {
// 1. 创建 XMLHttpRequest 对象
const xhr = new XMLHttpRequest();
// 2. 初始化请求
xhr.open(method, url, true);
// 3. 设置请求头
for (const key in headers) {
xhr.setRequestHeader(key, headers[key]);
}
// 4. 监听状态变化
xhr.onreadystatechange = function () {
if (xhr.readyState !== 4) return;
if (xhr.status >= 200 && xhr.status < 300) {
resolve(JSON.parse(xhr.responseText));
} else {
reject(new Error(`Request failed with status ${xhr.status}`));
}
};
// 5. 监听错误
xhr.onerror = function () {
reject(new Error('Network error'));
};
// 6. 发送请求
xhr.send(data ? JSON.stringify(data) : null);
});
}
// 使用示例
ajax({
method: 'GET',
url: 'https://api.example.com/users'
}).then(data => {
console.log(data);
}).catch(err => {
console.error(err);
});
Fetch API 方式
async function request(url, options = {}) {
const {
method = 'GET',
data = null,
headers = {},
timeout = 10000
} = options;
// 创建 AbortController 用于超时控制
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
try {
const response = await fetch(url, {
method,
headers: {
'Content-Type': 'application/json',
...headers
},
body: data ? JSON.stringify(data) : null,
signal: controller.signal
});
clearTimeout(timeoutId);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
if (error.name === 'AbortError') {
throw new Error('Request timeout');
}
throw error;
}
}
// 使用示例
request('https://api.example.com/users', {
method: 'POST',
data: { name: 'John' }
}).then(data => {
console.log(data);
});
封装通用请求类
class Http {
constructor(baseURL = '') {
this.baseURL = baseURL;
}
request(url, options) {
return fetch(this.baseURL + url, {
...options,
headers: {
'Content-Type': 'application/json',
...options.headers
},
body: options.body ? JSON.stringify(options.body) : null
}).then(res => {
if (!res.ok) throw new Error(res.statusText);
return res.json();
});
}
get(url, params = {}) {
const query = new URLSearchParams(params).toString();
const fullUrl = query ? `${url}?${query}` : url;
return this.request(fullUrl, { method: 'GET' });
}
post(url, data) {
return this.request(url, { method: 'POST', body: data });
}
put(url, data) {
return this.request(url, { method: 'PUT', body: data });
}
delete(url) {
return this.request(url, { method: 'DELETE' });
}
}
// 使用示例
const http = new Http('https://api.example.com');
http.get('/users', { page: 1 });
http.post('/users', { name: 'John' });
关键点
- XMLHttpRequest readyState:0-未初始化,1-已打开,2-已发送,3-接收中,4-完成
- Fetch 不会 reject HTTP 错误:需要手动检查
response.ok或response.status - Fetch 超时处理:使用
AbortController实现,XMLHttpRequest 可直接设置xhr.timeout - 跨域请求:需要服务端配置 CORS,或使用代理
- Fetch 优势:语法简洁、基于 Promise、支持 Stream
目录