前端请求大比拼:Fetch、Axios、Ajax、XHR
XHR
XMLHttpRequest 是一个内置的 JavaScript 对象,XMLHttpRequest(XHR)对象用于与服务器交互。
XMLHttpRequest 在 AJAX 编程中被大量使用。尽管名称包含 XML,XMLHttpRequest 也可以用于获取任何类型的数据,而不仅仅是 XML。它甚至支持 HTTP 以外的协议(包括 file:// 和 FTP)。
缺点 语法复杂 功能限制 XSRF(跨站请求伪造)保护 错误处理 仅限于浏览器环境
请求步骤
- 创建 XMLHttpRequest 对象:
let xhr = new XMLHttpRequest();
- 设置请求参数:
xhr.open("GET", "https://example.com/api/data", true);
- 设置请求头(可选):
xhr.setRequestHeader("Content-Type", "application/json");
- 监听状态变化:
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
// 请求成功,处理响应
console.log(xhr.responseText);
} else {
// 请求失败
console.error("请求失败");
}
}
};
- 发送请求
xhr.send();
readyStatus : 上面示例中的 readyState 是 XMLHttpRequest 对象的一个属性,用于表示请求的状态。该属性有以下五种可能的取值:
0 (未初始化): XMLHttpRequest 对象已创建,但尚未调用 open 方法。
1 (载入中): open 方法已调用,但尚未调用 send 方法。
2 (载入完成): send 方法已调用,并且响应头和响应状态已经可用。
3 (交互中): 正在接收响应数据,此时部分响应内容可能已经可以访问了。
4 (完成): 响应数据接收完成,整个请求过程已经完全结束。
常见的一些 HTTP 状态码包括:
200 OK:表示请求成功并返回所请求的数据。
201 Created:表示请求成功并在服务器上创建了新资源。
204 No Content:表示请求成功,但响应中无返回的内容。
400 Bad Request:表示请求有语法错误或参数错误,服务器无法理解。
401 Unauthorized:表示请求未经授权,需要用户进行身份验证。
403 Forbidden:表示服务器拒绝请求,通常是因为请求的资源没有访问权限。
404 Not Found:表示请求的资源不存在。
500 Internal Server Error:表示服务器内部发生错误,无法完成请求。
Ajax
AJAX(Asynchronous JavaScript and XML,异步 JavaScript 和 XML)是一种使用现有的网页技术来创建异步请求和更新页面内容的方法。
Ajax 是基于浏览器提供的 XMLHttpRequest 对象来实
// 创建 XMLHttpRequest 对象
const xhr = new XMLHttpRequest();
// 指定请求的方法和 URL
xhr.open("GET", "api_url", true); // 第三个参数 true 表示异步请求
// 设置请求头(如果需要)
xhr.setRequestHeader("Content-Type", "application/json"); // 根据实际需求设置请求头
// 注册一个回调函数来处理响应
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
const response = JSON.parse(xhr.responseText); // 处理响应数据
// 在这里执行相应的操作
console.log(response);
}
};
// 发送请求
xhr.send();
缺点
兼容性问题 代码冗余 缺乏默认配置 功能限制 可读性较差
Fetch
Fetch 是一种用于进行网络请求的现代 JavaScript API。
Fetch API 在浏览器中原生支持,并且以 Promise 为基础,使得异步请求更加直观和易用。使用 Fetch API,可以执行各种类型的请求(如 GET、POST、PUT、DELETE 等),发送请求时可以设置请求头、请求参数,以及处理响应数据。
相比 AJAX 优点:
Promise 支持 更简洁的 API 内置的 JSON 解析 更好的错误处理
fetch()
fetch(url, options)
.then((response) => {
// 在这里处理响应
})
.catch((error) => {
// 在这里处理错误
});
response()
fetch(url)
.then((response) => {
// 检查响应状态码
if (!response.ok) {
throw new Error("Network response was not ok");
}
// 定义一个响应类型与解析方法的映射关系
const responseTypes = new Map([
["json", () => response.json()],
["text", () => response.text()],
["formData", () => response.formData()],
["blob", () => response.blob()],
["arrayBuffer", () => response.arrayBuffer()],
]);
// 根据响应类型选择相应的解析方法
const parser = responseTypes.get(response.type);
if (parser) {
return parser();
} else {
throw new Error("Unsupported response type");
}
})
.then((data) => {
// 处理数据
console.log(data);
})
.catch((error) => {
// 处理错误情况
console.error("Error:", error);
});
错误处理
async function fetchData() {
try {
const response = await fetch("https://api.example.com/data");
if (response.ok) {
const data = await response.json();
console.log(data); // 处理解析后的数据
} else {
throw new Error("请求失败");
}
} catch (error) {
console.log(error); // 处理错误
}
}
fetchData();
Axios
Axios 是一个基于 Promise 网络请求库,用于在浏览器和 Node.js 中进行 HTTP 请求。在服务端它使用原生 node.js http 模块, 而在客户端 (浏览端) 则使用 XMLHttpRequests。
特点:
浏览器和 Node.js Promise API 请求拦截和响应拦截 取消请求 并发请求 自动转换数据 错误处理机制 简洁的 API
axios
.get("https://api.example.com/data")
.then((response) => {
// 处理成功响应
console.log(response.data);
})
.catch((error) => {
// 处理错误
console.error(error);
});
请求方法
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]])
多个请求
const axios = require("axios");
// 创建多个请求
const request1 = axios.get("https://api.example.com/data1");
const request2 = axios.get("https://api.example.com/data2");
// 并发发送多个请求
axios
.all([request1, request2])
.then(
axios.spread((response1, response2) => {
// 处理各个请求的响应
console.log(response1.data);
console.log(response2.data);
})
)
.catch((error) => {
// 处理错误
console.error(error);
});
请求拦截,响应拦截
在 Axios 中,可以使用 transformRequest 方法在请求发送之前对请求数据进行转换和处理,它是一个请求拦截器,是一个可选的函数。
axios({
url: "https://api.example.com/data",
method: "post",
data: {
id: 12345,
name: "John Doe",
},
transformRequest: (data, headers) => {
// 对请求数据进行转换和处理
const modifiedData = { ...data }; // 复制原始数据
// 修改数据或添加额外字段
modifiedData.extraField = "Extra Value";
// 修改请求头信息
headers["Content-Type"] = "application/json";
return JSON.stringify(modifiedData); // 返回处理后的数据
},
})
.then((response) => {
// 处理成功响应
console.log(response.data);
})
.catch((error) => {
// 处理错误
console.error(error);
});
axios
.get("https://api.example.com/data", {
transformResponse: (data) => {
// 对响应数据进行转换和处理
const parsedData = JSON.parse(data); // 解析 JSON 字符串
// 修改数据或添加额外字段
parsedData.extraField = "Extra Value";
return parsedData; // 返回处理后的数据
},
})
.then((response) => {
// 处理成功响应
console.log(response.data);
})
.catch((error) => {
// 处理错误
console.error(error);
});
拦截请求和响应
Axios 中,可以使用拦截器来拦截请求和响应,并在其被发送或接收之前进行一些额外的处理,可以通过 axios.interceptors 对象来添加拦截器。
// 添加请求拦截器
axios.interceptors.request.use(
(config) => {
// 在发送请求之前做一些处理
console.log("请求拦截器");
// 修改请求配置
config.headers["Authorization"] = "Bearer token";
return config;
},
(error) => {
// 处理请求错误
console.error("请求出错:", error);
}
);
// 添加响应拦截器
axios.interceptors.response.use(
(response) => {
// 在接收到响应数据之前做一些处理
console.log("响应拦截器");
// 修改响应数据
response.data = { ...response.data, extraField: "Extra Value" };
return response;
},
(error) => {
// 处理响应错误
console.error("响应出错:", error);
}
);
// 发送请求
axios
.get("https://api.example.com/data")
.then((response) => {
// 处理成功响应
console.log(response.data);
})
.catch((error) => {
// 处理请求或响应错误
console.error(error);
});
客户端支持 XSRF 防护
跨站请求伪造(简称 XSRF)是一种攻击 Web 应用的方法,其中攻击者将自己伪装成合法且受信任的用户,以影响应用程序与用户浏览器之间的交互。
const options = {
method: "post",
url: "/login",
xsrfCookieName: "XSRF-TOKEN",
xsrfHeaderName: "X-XSRF-TOKEN",
};
axios(options)
.then((response) => {
// 处理成功响应
console.log(response.data);
})
.catch((error) => {
// 处理请求错误
console.error(error);
});
请求进度 Axios 的另一个有趣的功能是能够监控请求的进度,这在下载或上传大文件时特别有用,可以使用 onUploadProgress 和 onDownloadProgress 两个配置选项来实现。
axios
.post("/upload", data, {
onUploadProgress: (progressEvent) => {
const percentCompleted = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
console.log(`上传进度:${percentCompleted}%`);
},
})
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.error(error);
});
axios
.get("/download", {
onDownloadProgress: (progressEvent) => {
const percentCompleted = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
console.log(`下载进度:${percentCompleted}%`);
},
})
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.error(error);
});
取消请求
在 Axios 中,可以使用取消令牌(cancel token)来取消请求。取消令牌是一个对象,它表示一个具体的取消操作,并允许在需要时中止请求。
// 创建一个取消令牌源
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
// 发送请求
axios
.get("/api/data", {
cancelToken: source.token,
})
.then((response) => {
console.log(response.data);
})
.catch((error) => {
if (axios.isCancel(error)) {
console.log("请求已被取消:", error.message);
} else {
console.error(error);
}
});
// 取消请求
source.cancel("取消请求的原因");
总结
相对于 Fetch、XMLHttpRequest 和 Ajax,我还是更喜欢 Axios。它提供了简洁易用的 API,统一的错误处理和拦截器支持,取消请求和超时处理功能,以及基于 Promise 的链式调用和跨浏览器兼容性。这些特性使得使用 Axios 更方便、高效,并提供更好的开发体验。