AJAX 简介
AJAX 是什么、XMLHttpRequest 的工作流程、同步与异步。
四步流程
const xhr = new XMLHttpRequest(); // 1. 创建
xhr.open('GET', 'data.asp?q=asp'); // 2. 配置
xhr.onreadystatechange = function () { // 3. 监听
if (xhr.readyState === 4 && xhr.status === 200) {
document.getElementById('out').textContent = xhr.responseText;
}
};
xhr.send(); // 4. 发送| readyState | Meaning |
|---|---|
| 0 | 还没调用 open |
| 1 | open 调过了 |
| 2 | 请求已发出 |
| 3 | 收到部分响应 |
| 4 | 响应全部到达 |
fetch 写法
const res = await fetch('data.asp?q=asp');
if (!res.ok) throw new Error('HTTP ' + res.status);
const text = await res.text();
document.getElementById('out').textContent = text;fetch is the modern replacement, Promise-based and much shorter. Note it does not reject on 404/500 — only on network failure — so check res.ok yourself.
POST 提交 JSON
const res = await fetch('save.asp', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Ada', age: 36 })
});
const data = await res.json();<%
Response.ContentType = "application/json"
Response.Charset = "UTF-8"
' 经典 ASP 没有内置 JSON 解析,需自己读请求体
Dim body
body = Request.BinaryRead(Request.TotalBytes)
' 或用第三方 JSON 库解析 body
Response.Write "{""ok"":true}"
%>Request.Form cannot read an application/json body; it only parses form encodings. Receiving JSON needs BinaryRead plus your own parser — the awkward part of AJAX in classic ASP.
同步 vs 异步
// 异步(默认):不阻塞,界面照常响应
xhr.open('GET', 'slow.asp', true);
// 同步:浏览器会卡住直到响应到达(已不推荐,主线程会被警告)
xhr.open('GET', 'slow.asp', false);A synchronous request freezes the page: no clicks, no scrolling, no animation. Modern browsers warn about synchronous XHR on the main thread and forbid it in some contexts. Always use async.
<table>...</table> for innerHTML looks convenient but invites XSS and makes the data unusable elsewhere.跨域
// 请求别的域名时,浏览器会先发 OPTIONS 预检
fetch('https://api.other.com/data', { credentials: 'include' });<%
Response.AddHeader "Access-Control-Allow-Origin", "https://app.example.com"
Response.AddHeader "Access-Control-Allow-Methods", "GET, POST, OPTIONS"
Response.AddHeader "Access-Control-Allow-Headers", "Content-Type"
Response.AddHeader "Access-Control-Allow-Credentials", "true"
If Request.ServerVariables("REQUEST_METHOD") = "OPTIONS" Then
Response.End
End If
%>Access-Control-Allow-Origin: * cannot be combined with credentials. To send cookies you must name the exact origin — no wildcards.
四步流程
const xhr = new XMLHttpRequest(); // 1. 创建
xhr.open('GET', 'data.asp?q=asp'); // 2. 配置
xhr.onreadystatechange = function () { // 3. 监听
if (xhr.readyState === 4 && xhr.status === 200) {
document.getElementById('out').textContent = xhr.responseText;
}
};
xhr.send(); // 4. 发送| 状态 | 含义 |
|---|---|
| 未初始化 | 还没调用 open |
| 已打开 | open 调过了 |
| 已发送 | 请求已发出 |
| 接收中 | 收到部分响应 |
| 完成 | 响应全部到达 |
fetch 写法
const res = await fetch('data.asp?q=asp');
if (!res.ok) throw new Error('HTTP ' + res.status);
const text = await res.text();
document.getElementById('out').textContent = text;fetch 是 XHR 的现代替代,基于 Promise,代码短很多。注意它不会因为 404/500 而 reject——只有网络故障才 reject,所以必须自己检查 res.ok。
POST 提交 JSON
const res = await fetch('save.asp', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Ada', age: 36 })
});
const data = await res.json();<%
Response.ContentType = "application/json"
Response.Charset = "UTF-8"
' 经典 ASP 没有内置 JSON 解析,需自己读请求体
Dim body
body = Request.BinaryRead(Request.TotalBytes)
' 或用第三方 JSON 库解析 body
Response.Write "{""ok"":true}"
%>Request.Form 读不了 application/json 的请求体,因为它只解析表单编码。要接收 JSON 必须 BinaryRead 原始字节再自己解析——这是经典 ASP 处理 AJAX 最麻烦的一点。
同步 vs 异步
// 异步(默认):不阻塞,界面照常响应
xhr.open('GET', 'slow.asp', true);
// 同步:浏览器会卡住直到响应到达(已不推荐,主线程会被警告)
xhr.open('GET', 'slow.asp', false);同步请求会让整个页面冻结——用户点不了、滚不动、动画停止。现代浏览器已对主线程上的同步 XHR 发出警告,某些场景直接禁止。永远用异步。
<table>...</table> 再 innerHTML 塞进去,看起来省事,但拼接 HTML 极易引入 XSS,且前端无法复用数据。跨域
// 请求别的域名时,浏览器会先发 OPTIONS 预检
fetch('https://api.other.com/data', { credentials: 'include' });<%
Response.AddHeader "Access-Control-Allow-Origin", "https://app.example.com"
Response.AddHeader "Access-Control-Allow-Methods", "GET, POST, OPTIONS"
Response.AddHeader "Access-Control-Allow-Headers", "Content-Type"
Response.AddHeader "Access-Control-Allow-Credentials", "true"
If Request.ServerVariables("REQUEST_METHOD") = "OPTIONS" Then
Response.End
End If
%>Access-Control-Allow-Origin 写 * 时不能同时允许凭证(Cookie)。要带 Cookie 就必须写明具体域名,且不能是通配符。