AJAX(Asynchronous JavaScript and XML) 通过在后台与服务器交换少量数据,实现网页的异步更新,避免整个页面刷新。
工作原理: 创建XMLHttpRequest对象:浏览器内置对象,用于与服务器交互 配置请求参数:设置请求方法、URL、异步标志等 发送请求:向服务器发送HTTP请求 监听状态变化:通过事件监听请求状态 处理响应:服务器返回数据后进行处理// 原生AJAX请求流程
用户界面 → JavaScript调用XMLHttpRequest → HTTP请求 → 服务器
服务器 → XML/JSON数据 → XMLHttpRequest回调函数 → 更新页面
// 兼容性写法
function createXHR() {
if (window.XMLHttpRequest) {
// 现代浏览器
return new XMLHttpRequest();
} else {
// 旧版IE
return new ActiveXObject("Microsoft.XMLHTTP");
}
}
var xhr = createXHR();
// 1. 创建对象
var xhr = new XMLHttpRequest();
// 2. 配置请求
xhr.open('GET', 'https://api.example.com/data', true); // true表示异步
// 3. 设置请求头(可选)
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Authorization', 'Bearer token123');
// 4. 监听状态变化
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) { // 请求完成
if (xhr.status >= 200 && xhr.status < 300) { // 成功状态码
var data = JSON.parse(xhr.responseText);
console.log('成功:', data);
} else {
console.error('请求失败:', xhr.status);
}
}
};
// 5. 发送请求
xhr.send();
// POST请求示例
xhr.open('POST', 'https://api.example.com/data', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('name=John&age=25');
0: 未初始化 - XMLHttpRequest对象已创建
1: 已打开 - open()方法已调用
2: 已发送 - send()方法已调用
3: 接收中 - 正在接收响应数据
4: 完成 - 响应数据接收完成
var xhr = new XMLHttpRequest();
// 进度事件
xhr.onloadstart = function() { console.log('开始加载'); };
xhr.onprogress = function(event) {
if (event.lengthComputable) {
var percent = (event.loaded / event.total) * 100;
console.log('加载进度:', percent + '%');
}
};
// 加载完成
xhr.onload = function() {
if (xhr.status === 200) {
console.log('请求成功:', xhr.response);
}
};
// 错误处理
xhr.onerror = function() {
console.error('网络请求失败');
};
// 超时处理
xhr.timeout = 5000; // 5秒超时
xhr.ontimeout = function() {
console.error('请求超时');
};
xhr.open('GET', 'api/data', true);
xhr.send();
$.ajax({
url: 'api/data', // 请求地址
type: 'GET', // 请求方法 GET/POST/PUT/DELETE
dataType: 'json', // 预期返回数据类型
data: { // 发送到服务器的数据
id: 1,
name: 'John'
},
success: function(data) { // 请求成功回调
console.log('成功:', data);
},
error: function(xhr, status, error) { // 请求失败回调
console.error('失败:', error);
},
complete: function(xhr, status) { // 请求完成回调(无论成功失败)
console.log('请求完成');
}
});
$.ajax({
url: 'api/data',
type: 'POST',
// 数据相关
data: JSON.stringify({user: 'John'}), // 可发送字符串
contentType: 'application/json', // 发送数据的类型
dataType: 'json', // 预期服务器返回类型
// 请求头设置
headers: {
'Authorization': 'Bearer token123',
'Custom-Header': 'value'
},
// 异步控制
async: true, // 默认true(异步)
timeout: 3000, // 超时时间(毫秒)
// 回调函数
beforeSend: function(xhr) {
// 发送前可修改请求头
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
console.log('正在发送请求...');
},
success: function(data, status, xhr) {
console.log('请求成功', data);
},
error: function(xhr, status, error) {
console.error('状态码:', xhr.status);
console.error('错误信息:', error);
},
complete: function(xhr, status) {
console.log('请求完成,状态:', status);
}
});
// GET请求
$.get('api/data', {id: 1}, function(data) {
console.log(data);
}, 'json');
// POST请求
$.post('api/save', {name: 'John'}, function(data) {
console.log(data);
});
// 加载HTML内容到元素
$('#result').load('partials/content.html #section');
// 获取JSON数据
$.getJSON('api/data.json', function(data) {
console.log(data);
});
// 链式调用
$.ajax('api/data')
.done(function(data) {
console.log('成功:', data);
})
.fail(function(xhr, status, error) {
console.error('失败:', error);
})
.always(function() {
console.log('请求完成');
});
// 多个请求
$.when(
$.ajax('api/users'),
$.ajax('api/products')
).then(function(usersResponse, productsResponse) {
var users = usersResponse[0];
var products = productsResponse[0];
console.log('所有请求完成', users, products);
});
// 使用FormData上传文件
var formData = new FormData();
formData.append('file', fileInput.files[0]);
$.ajax({
url: 'api/upload',
type: 'POST',
data: formData,
processData: false, // 不处理数据
contentType: false, // 不设置内容类型
// 上传进度
xhr: function() {
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', function(e) {
if (e.lengthComputable) {
var percent = Math.round((e.loaded / e.total) * 100);
$('#progress-bar').width(percent + '%');
}
});
return xhr;
},
success: function(response) {
console.log('上传成功:', response);
}
});
// 原生AJAX
var xhr = new XMLHttpRequest();
xhr.open('GET', 'api/long-running', true);
xhr.send();
// 取消请求
document.getElementById('cancel-btn').addEventListener('click', function() {
xhr.abort();
console.log('请求已取消');
});
// jQuery
var jqXHR = $.ajax('api/data');
jqXHR.abort(); // 取消请求
// 设置全局AJAX配置
$.ajaxSetup({
timeout: 5000,
error: function(xhr, status, error) {
switch(xhr.status) {
case 401:
alert('请先登录');
window.location.href = '/login';
break;
case 403:
alert('没有权限');
break;
case 404:
alert('资源不存在');
break;
case 500:
alert('服务器错误');
break;
default:
console.error('请求错误:', error);
}
}
});
// 发送请求(自动应用全局配置)
$.ajax({
url: 'api/data',
success: function(data) {
// 处理数据
}
});
// 缓存控制
$.ajax({
url: 'api/data',
cache: false, // 禁止缓存
// 或
headers: {
'Cache-Control': 'no-cache'
}
});
// 节流控制
var requestTimer;
function search(query) {
clearTimeout(requestTimer);
requestTimer = setTimeout(function() {
$.get('api/search', {q: query}, function(data) {
// 显示结果
});
}, 300); // 300ms延迟
}
// 特征检测
if (window.XMLHttpRequest) {
// 支持现代AJAX
var xhr = new XMLHttpRequest();
} else if (window.ActiveXObject) {
// IE6及以下
try {
var xhr = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
var xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
}
// 回退方案
function makeRequest(url, success, error) {
if (window.XMLHttpRequest) {
// 使用AJAX
$.ajax({
url: url,
success: success,
error: error
});
} else {
// 使用JSONP或其他替代方案
var script = document.createElement('script');
script.src = url + '?callback=handleResponse';
document.head.appendChild(script);
}
}
虽然AJAX仍然有效,但现代开发更推荐:
Fetch API:更现代、更强大的原生API
fetch('api/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
Axios:流行的HTTP客户端库
axios.get('api/data')
.then(response => console.log(response.data))
.catch(error => console.error(error));
掌握AJAX原理对于理解现代Web开发至关重要,虽然现在有更多现代工具,但理解底层原理有助于更好地解决问题和进行性能优化。