Ajax 复习笔记
1. 什么是 XML
可扩展标记语言,被设计用来传输和存储数据,全部是自定义标签,用来表示数据,目前被 JSON 替代。
2. AJAX 的优缺点
AJAX(Asynchronous JavaScript and XML)即"异步 JavaScript 和 XML",指一种创建交互式网页应用的网页开发技术。
优点:
- 异步请求,不阻塞页面其他操作。
- 按需取数据,减少不必要的数据传输。
- 局部刷新,用户体验更好。
- 可以与服务器保持连接(如 Comet、长轮询)。
缺点:
- 破坏浏览器后退按钮的正常行为(因为是异步更新页面内容)。
- 依赖 JavaScript,需要考虑浏览器兼容性。
- 不利于 SEO(爬虫看不到异步加载的数据)。
- 存在跨域问题。
3. 使用 XMLHttpRequest 发送网络请求
const xhr = new XMLHttpRequest();
xhr.open(method, url);
// 设置请求头, 一般不设置
xhr.setRequestHeader("Content-type", "..");
// 发送请求
// get 请求体为空, post 可以不为空
xhr.send(body);
// 响应请求
// xhr.responseXML 接受 xml 格式的响应数据
// xhr.responseText 接收 text 格式的响应数据
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
const test = xhr.responseText;
}
}
4. 避免缓存
在一些浏览器中(IE),由于缓存机制的存在,ajax 只会发送的第一次请求,剩余多次请求不会再发送给浏览器而是直接加载缓存中的数据。
浏览器的缓存是根据 url 地址来记录的,所以我们只需要修改 url 地址即可避免缓存问题:
xhr.open("get", "xx/x?t=" + Date.now());
5. AJAX 请求状态
使用 xhr.readyState 可以查看请求当前的状态:
| readyState | 状态 |
|---|---|
| 0 | 未初始化,尚未调用 open() |
| 1 | open() 已调用 |
| 2 | send() 已调用 |
| 3 | 正在接收响应 |
| 4 | 响应接收完毕 |
6. 响应体内容转化
手动转化:
let data = JSON.parse(xhr.response);
自动转化:
xhr.responseType = "json";
如此设置的话,响应数据将会自动按照 JSON 格式转化为对象。
7. 超时设置、超时回调、错误回调与取消请求
xhr.timeout = 2000;
xhr.ontimeout = function () {}; // 超时回调函数
xhr.onerror = function () {}; // 错误回调函数
xhr.abort(); // 取消请求
axios 配合 AbortController 或 CancelToken 实现取消请求:
// 方式一
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios.get("xxxx", { cancelToken: source.token });
source.cancel("主动取消请求");
// 方式二
const CancelToken = axios.CancelToken;
let cancel;
axios.get("xxxx", {
cancelToken: new CancelToken(function executor(c) { cancel = c; })
});
cancel("主动取消请求");
8. 请求报文与响应报文结构
请求报文:
- 请求行:请求类型 / URL(路径或查询字符串) / HTTP 协议版本,例如
GET 或 POST /s?ie=utf-8 HTTP/1.1 - 请求头:名字: 值,例如
Host: atguigu.com、Cookie: name=guigu、Content-Type: ... - 空行
- 请求体:GET 请求为空;POST 请求可以不为空,例如
username=admin&password=admin
响应报文:
- 状态行:HTTP 协议版本 / 响应状态码 / 状态字符串,例如
HTTP/1.1 200 OK - 响应头:名字: 值,例如
Content-Type: text/html;charset=utf-8等 - 空行
- 响应体:HTML / JSON 等内容
9. 用 Express 监听 GET/POST 请求并实现跨域
// 引入 express
const express = require("express");
// 创建应用对象
const app = express();
// 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
// /server 是向服务器请求的 URL
app.get("/server", (request, response) => {
// 设置响应头, 设置允许跨域
response.setHeader("Access-Control-Allow-Origin", "*");
// 设置响应体
response.send("HELLO AJAX");
});
app.post("/server", (request, response) => {
response.setHeader("Access-Control-Allow-Origin", "*");
response.send("HELLO AJAX POST");
});
// 可以接收任意类型的请求
app.all("/server", (request, response) => {
response.setHeader("Access-Control-Allow-Origin", "*");
// 设置可以接受任意的响应头键值对
response.setHeader("Access-Control-Allow-Headers", "*");
response.send("HELLO AJAX POST");
});
// 监听端口启动服务
app.listen(8000, () => {
console.log("8000 端口监听,服务已启动");
});
10. jQuery 发送 AJAX 请求
get
$.get(url, [dataType], [callback 载入成功回调函数], [err 回调函数])
type: xml, html, script, json, text, _default
post
$.post(url, [dataType], [callback], [err 回调函数])
$.ajax()
$.ajax({
type: "get",
url: "",
data: {...},
dataType: "json",
timeout: 2000,
success: function (data, testStatus) {},
error: function (XMLHttpRequest, testStatus, errorThrown) {
// XMLHttpRequest, 错误信息, 捕获的错误对象
},
headers: {
c: 300
}
})
11. axios 发送 AJAX
npm i axios
创建实例:
const instance = axios.create({
baseURL: "",
timeout: 1000,
headers: {}
});
实例方法:
axios#request(config)axios#get(url[, config])axios#delete(url[, config])axios#head(url[, config])axios#options(url[, config])axios#post(url[, data[, config]])axios#put(url[, data[, config]])axios#patch(url[, data[, config]])
get:
axios.default.baseURL = "BASEurl";
axios.get(url, {
params: { id: 100 }, // 与请求一起发送的 url 参数
headers: { name: "liqingy" },
timeout: 2000
}).then(res => {
console.log(res.data);
console.log(res.status);
console.log(res.statusText);
console.log(res.headers);
console.log(res.config);
});
post:
axios.post(url,
{
// 作为请求体被发送的数据
// 只能被应用于 put post patch
username: "admin"
},
{
params: { id: 100 }, // url 参数
headers: { name: "liqingyang" } // 请求头信息
}
).then(res => {}).catch(reason => {});
axios 函数形式发送 AJAX:
axios({
url: "",
method: "POST",
params: { vip: 10, level: 30 }, // url 参数
headers: { a: 100, b: 200 }, // 请求头信息
data: { username: "admin", password: "admin" } // 请求体信息
}).then(res => {
console.log(res.status); // 响应状态码
console.log(res.statusText); // 响应状态字符串
console.log(res.headers); // 响应头信息
console.log(res.data); // 响应体
});
12. jQuery 发送 JSONP
$.getJSON("url", 回调函数)
URL 中一定要有 callback=? 请求参数。该参数在页面中创建一个调用函数,并且发送给服务端,服务端利用 request.query.callback 可以直到该函数名,并且返回调用函数及实参。
前端:
$.getJSON("url/jquery-jsonp-server?callback=xixi", function (data) {
$("#result").html(`
名称: ${data.name}<br>
校区: ${data.city}
`);
});
服务器:
app.all("jquery-jsonp-server", (request, response) => {
const data = { name: "liqingyang", city: ["beijing"] };
let cb = request.query.callback;
let str = JSON.stringify(data);
response.send(`${cb}(${str})`);
});
13. 什么是跨域 以及 解决方法
同源策略:浏览器安全策略。同源要求协议、域名、端口号完全相同,违背同源策略就是跨域。
JSONP:只支持 get 请求。利用一些标签天生的跨域能力,比如 img、script、iframe、link。
动态地创建一个 img 标签,设置 img 的 src,将 src 添加到 body 中:
const img = document.createElement("img");
img.src = "url";
document.body.appendChild(img);
举例:客户端发送请求,服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。
首先,网页动态插入 <script> 元素,由它向跨源网址发出请求:
function addScriptTag(src) {
var script = document.createElement("script");
script.setAttribute("type", "text/javascript");
script.src = src;
document.body.appendChild(script);
}
window.onload = function () {
addScriptTag("http://example.com/ip?callback=foo");
}
function foo(data) {
console.log("Your public IP address is: " + data.ip);
}
上面代码通过动态添加 <script> 元素,向服务器 example.com 发出请求。注意,该请求的查询字符串有一个 callback 参数,用来指定回调函数的名字,这对于 JSONP 是必需的。
服务器收到这个请求以后,会将数据放在回调函数的参数位置返回:
foo({ "ip": "8.8.8.8" });
由于 <script> 元素请求的脚本,直接作为代码运行。这时,只要浏览器定义了 foo 函数,该函数就会立即调用。作为参数的 JSON 数据被视为 JavaScript 对象,而不是字符串,因此避免了使用 JSON.parse 的步骤。
CORS 跨域资源共享:支持 get/post 请求,完全在服务器中进行处理。
CORS 新增了一组 HTTP 首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源。
CORS 通过设置一个响应头来告诉浏览器,该请求允许跨域:
// 服务器设置响应头
res.set("Access-Control-Allow-Origin", "url 或者 *");
WebSocket:WebSocket 是一种通信协议,使用 ws://(非加密)/ wss://(加密)作为协议前缀,该协议不实行同源策略。
WebSocket 发送请求的头信息有一个字段 Origin,表示该请求的请求源,即发自哪个域名。正是因为这个 WebSocket 才没有实行同源策略,因为服务器可以根据这个判断可否许可本次通信。
14. Cookie
Cookie 是服务器写入浏览器的一小段信息,只有同源的网页才能共享。但是,两个网页一级域名相同,只是二级域名不同,浏览器允许通过设置 document.domain 共享 Cookie。
举例来说,A 网页是 http://w1.example.com/a.html,B 网页是 http://w2.example.com/b.html,那么只要设置相同的 document.domain,两个网页就可以共享 Cookie:
document.domain = "example.com";
另外,服务器也可以在设置 Cookie 的时候,指定 Cookie 的所属域名为一级域名,比如 .example.com:
Set-Cookie: key=value; domain=.example.com; path=/
这样的话,二级域名和三级域名不用做任何设置,都可以读取这个 Cookie。
补充
补充:本篇是 Ajax 复习笔记,覆盖 XML、AJAX 优缺点、XHR 用法、jQuery AJAX、跨域方案、Cookie、请求/响应报文结构、Express 跨域监听、响应体转化、超时取消、axios 与 JSONP 实现等。
关键速记:
- XHR 五个 readyState:
0 未初始化 → 1 open() 已调用 → 2 send() 已调用 → 3 接收到部分响应 → 4 完成。 - HTTP 状态码范围:
2xx 成功、3xx 重定向、4xx 客户端错误、5xx 服务端错误。 - 跨域三种方案:
- JSONP:利用
<script>跨域特性,仅支持 GET,需服务端配合 callback。 - CORS:服务端设置
Access-Control-Allow-Origin,浏览器自动放行,简单请求直接发,预检请求先 OPTIONS。 - WebSocket / PostMessage / Nginx 反代:其他常见方案。
- JSONP:利用
- 避免缓存:URL 加时间戳
?t=Date.now(),或设置请求头Cache-Control: no-cache。 - 请求报文三段:请求行(方法 + URL + HTTP 版本)、请求头、空行、请求体(POST 携带表单或 JSON)。
- Express 监听:
app.get/post/all("/server", handler),跨域通过Access-Control-Allow-Origin响应头实现。 - axios 实例:
axios.create({ baseURL, timeout, headers }),全局默认可用axios.defaults.baseURL。 - 超时 / 取消:
xhr.timeout = 2000; xhr.ontimeout = () => {}xhr.abort()- axios 配合
AbortController或CancelToken。
- jQuery JSONP:
$.getJSON(url + "?callback=fn", cb),服务端用request.query.callback拼成函数调用返回。
补充:现代项目几乎都用 axios / fetch,XHR 主要用于面试复习和理解底层原理;现代工程实践里 axios + 服务端 RESTful 接口是主流,JSONP 几乎只在维护老项目或解决特殊跨域场景时才会用。
来源整理自:我的有道云笔记



