JavaScript 发起网络请求 axios、fetch、async / await
目录
fetch
发送 GET 请求(fetch)
发送 POST 请求(fetch)
处理后台异常响应
async / await
async
await
发送 GET 请求(async / await fetch)
发送 POST 请求(async / await fetch)
Axios
发送 GET 请求(axios)
发送 POST 请求(axios)
发送 GET 请求(async / await axios)
发送 POST 请求(async / await axios)
请求拦截器
响应拦截器
取消请求
中止请求
fetch
fetch 是现代浏览器中用于发起网络请求的 API,它提供了一种更加简洁和强大的方式来获取资源(例如从网络加载数据)。与传统的 XMLHttpRequest 相比,fetch 提供了更简洁的语法和更强的功能,并且返回的是 Promise,使得异步编程更加易于理解和处理。
fetch 允许我们通过 HTTP 请求(如 GET、POST、PUT、DELETE 等方法)向服务器请求数据,并异步地处理请求结果。它是异步的,意味着不会阻塞其他 JavaScript 代码的执行。
语法:
fetch(url, options)
.then(response => response.json()) // 将响应体解析为 JSON
.then(data => console.log(data)) // 处理返回的数据
.catch(error => console.error('Error:', error)); // 错误处理
参数说明:
- url: 请求的目标 URL(可以是相对路径或绝对路径)。
- options: 可选的配置对象,包含请求方法、头信息、请求体等。
options 常用选项:
method:请求方式,默认为 GET。常见值有 POST、PUT、DELETE、PATCH 等。
示例:
fetch('https://example.com', { method: 'POST', });
headers:请求头,通常是一个对象,包含键值对。
示例:
fetch('https://example.com', { headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer token', } });
body:请求体,仅在方法是 POST、PUT 等时使用,通常是 JSON 格式的数据。
示例:
fetch('https://example.com', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'John', age: 30 }) });
mode:控制请求的跨域行为,常用的值有 no-cors、cors 和 same-origin。默认为 cors。
- no-cors:不携带跨域凭证,限制请求返回内容的访问。
- cors:允许跨域请求,需目标服务器支持 CORS。
- same-origin:仅允许同源请求(即相同的协议、域名和端口)。
示例:
fetch('https://example.com', { mode: 'no-cors', // 不发送跨域请求 });
cache:控制缓存行为,常用值有 default、no-store、reload 等。
- default:按常规缓存机制处理,有缓存就用缓存,没有缓存就从网络加载。
- no-store:不缓存,始终从网络加载。
- reload:强制重新加载,不使用缓存(一点缓存不能用,确保从网络加载最新数据)。
- no-cache:查找缓存并验证(缓存可用返回304 状态码),缓存不可用重新从网络加载。
- force-cache:强制使用缓存,如果没有则从网络加载。
- only-if-cached:只使用缓存,缓存没有则不请求。
示例:
fetch('https://example.com', { cache: 'no-cache', // 禁用缓存 });
credentials:控制是否发送 cookies、http认证信息等,常见值有 same-origin 和 include。
- same-origin:仅在同源请求时自动携带凭证(默认)。
- include:无论同源还是跨域请求,都携带凭证。
- omit:请求不携带凭证,适用于公开资源或不需要身份验证的请求。
示例:
fetch('https://example.com', { credentials: 'include' });
发送 GET 请求(fetch)
示例:
fetch('http://127.0.0.1:8080/test?name=123')
.then(response => response.json()) // 解析 JSON 响应,// 这个 response.json() 不是返回的数据,还要调用 response.json() 函数,等待处理完成返回给下一个 then 才是处理好的数据
.then(data => {
console.log(data); // 输出后台返回的数据
})
.catch(error => console.error('Error:', error)); // 错误处理
发送 POST 请求(fetch)
示例: 请求头:Content-Type: application/x-www-form-urlencoded
const data = {
name: 'Tom'
};
// 将对象转换为 x-www-form-urlencoded 格式
const urlEncodedData = new URLSearchParams(data).toString();
fetch('http://127.0.0.1:8080/test', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: urlEncodedData,
})
.then(response => response.json()) // 解析 JSON 响应 // 这个 response.json() 不是返回的数据,还要调用 response.json() 函数,等待处理完成返回给下一个 then 才是处理好的数据
.then(data => {
console.log(data); // 输出后台返回的数据
})
.catch(error => console.error('Error:', error)); // 错误处理
示例: 请求头:Content-Type: application/json
fetch('http://127.0.0.1:8080/test', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'Tom'
}),
})
.then(response => response.json()) // 解析 JSON 响应 // 这个 response.json() 不是返回的数据,还要调用 response.json() 函数,等待处理完成返回给下一个 then 才是处理好的数据
.then(data => {
console.log(data); // 输出后台返回的数据
})
.catch(error => console.error('Error:', error)); // 错误处理
处理后台异常响应
fetch 只会在网络失败或请求被阻止时拒绝 Promise。对于 4xx 或 5xx 错误(如 404 或 500),它依然会返回一个 fulfilled (已完成)状态的 Promise,所以需要手动检查 response.ok 来判断请求是否成功。
示例:
fetch('http://127.0.0.1:8080/test?name=123')
.then(response => {
// 处理后台程序异常的返回,例如 500
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
console.log(data);
})
.catch(error => console.error('Error:', error));
async / await
async / await 是 JavaScript 中用来处理异步操作的一种语法糖,它基于 Promise,使得处理异步代码变得更加简洁和易读。async/await 主要是为了替代 .then() 的链式调用,目的是让异步代码更加简洁和可读。虽然 fetch 本身是异步的,使用 async/await 使得你可以像写同步代码一样处理异步操作,从而避免了嵌套 .then() 造成的“回调地狱”(callback hell)问题。
async
async 是一个用于声明异步函数的关键字。它告诉 JavaScript 引擎,这个函数是异步的,返回的结果会是一个 Promise 对象。
当你声明一个 async 函数时,无论函数内部是否有 return,它都会自动返回一个 Promise。如果你在函数内部返回一个值,Promise 会自动将该值包装起来。
语法:
async function foo() {
// 异步操作
}
console.log(foo()); // 打印 Promise { undefined },表示是一个Promise对象
示例:
// 定义一个 async 函数
async function foo() {
return "Hello World";
}
// 调用 async 函数,调用 then 函数处理 async 返回结果。
foo().then((result) => {
console.log(result);
});
await
await 用于等待一个 Promise 对象的结果,它只能在 async 函数内部使用。当遇到 await 时,JavaScript 会暂停 async 函数的执行,等待 Promise 被解析(resolved)或拒绝(rejected)后再继续执行。
没有 await 时: async 函数返回一个 Promise,你需要使用 .then() 或 .catch() 来处理这个 Promise 的结果。
有 await 时: await 会暂停 async 函数的执行,直到 async 函数的返回结果 Promise 被解析,并返回解析的结果给 await。你可以直接在 async 函数内部处理异步结果,而不需要在 async 函数外部使用 .then() 来处理结果了。
示例对比: // 没用 await 时
async function foo() {
return "Hello, World!";
}
// 没有 await 时,这样处理 async 的返回结果
foo().then(result => {
console.log(result); // 输出: "Hello, World!"
});
示例对比: // 使用 await 时
async function foo() {
// 有 await 时,直接在这里等待 async 函数的返回结果,然后在 async 函数内部就把返回结果处理了。
const result = await "Hello, World!";
console.log(result); // 输出: "Hello, World!"
}
foo();
发送 GET 请求(async / await fetch)
示例:
// 创建一个 async 函数
async function get() {
// 使用 await fetch 发送 GET 请求
const response = await fetch('http://127.0.0.1:8080/test?name=123');
// 判断请求后台是否异常
if (!response.ok) {
throw new Error('请求失败,状态码:' + response.status);
}
const data = await response.json(); // 解析 JSON 响应体,这一步相当于 .then(response => response.json())
console.log(data); // 输出后台返回的数据
}
// 调用 async 函数
get().catch(error => console.error('Error:', error));
发送 POST 请求(async / await fetch)
示例: 请求头:Content-Type: application/x-www-form-urlencoded
// 创建一个 async 函数
async function post() {
// 请求体的数据,使用 URLSearchParams 对象,创建 x-www-form-urlencoded 数据格式的对象
const formData = new URLSearchParams();
formData.append('name', 'Tom'); // 请求参数
// 使用 await fetch 发送 POST 请求
const response = await fetch('http://127.0.0.1:8080/test', {
method: 'POST', // 设置请求方法为 POST
headers: {
'Content-Type': 'application/x-www-form-urlencoded', // 设置请求头
},
body: formData, // 发送表单数据
});
// 判断请求后台是否异常
if (!response.ok) {
throw new Error('请求失败,状态码:' + response.status);
}
const data = await response.json(); // 解析 JSON 响应体,这一步相当于 .then(response => response.json())
console.log(data); // 输出后台返回的数据
}
// 调用 async 函数
post().catch(error => console.error('Error:', error));
示例: 请求头:Content-Type: application/json
// 创建一个 async 函数
async function post() {
// 请求参数:一个 JSON 对象
const requestBody = {
name: 'Tom'
};
try {
// 使用 await fetch 发送 POST 请求
const response = await fetch('http://127.0.0.1:8080/test', {
method: 'POST', // 设置请求方法为 POST
headers: {
'Content-Type': 'application/json', // 设置请求头
},
body: JSON.stringify(requestBody), // 发送json数据
});
// 判断请求后台是否异常
if (!response.ok) {
throw new Error('请求失败,状态码:' + response.status);
}
const data = await response.json(); // 解析 JSON 响应体,这一步相当于 .then(response => response.json())
console.log(data); // 输出后台返回的数据
} catch (error) {
console.error('Error:', error)
}
}
// 调用 async 函数
post();
Axios
Axios 是一个基于 Promise 的 HTTP 客户端,用于浏览器和 Node.js 环境中发送 HTTP 请求。它支持发送 GET、POST、PUT、DELETE 等常见的 HTTP 请求,并能够处理响应数据。
安装 Axios,这里以 Node.js 环境为例
npm install axios
Axios 的常用方法:
- axios.get(url [, config]):发送一个 GET 请求。url 是请求的目标 URL,config 是可选的配置对象。
- axios.post(url [, data [, config]]):发送一个 POST 请求。url 是目标 URL,data 是请求体数据,config 是可选的配置对象。
- axios.put(url [, data [, config]]):发送一个 PUT 请求。url 是目标 URL,data 是请求体数据,config 是可选的配置对象。
- axios.delete(url [, config]):发送一个 DELETE 请求。url 是目标 URL,config 是可选的配置对象。
- axios.head(url [, config]):发送一个 HEAD 请求,通常用于获取响应头信息。url 是目标 URL,config 是可选的配置对象。
- axios.options(url [, config]):发送一个 OPTIONS 请求,通常用于获取服务器支持的 HTTP 方法。url 是目标 URL,config 是可选的配置对象。
- axios.patch(url [, data [, config]]):发送一个 PATCH 请求,用于对资源进行部分更新。url 是目标 URL,data 是请求体数据,config 是可选的配置对象。
- axios.all(iterable):并行发送多个请求,iterable 是一个数组,包含多个 Promise 对象。axios.all() 方法返回一个新的 Promise,在所有请求完成后,才会执行 then 方法。
- axios.spread(callback):用于 axios.all() 方法返回的多个响应结果展开。它将多个参数分配给传入的回调函数。
- axios.create([config]):创建一个新的 Axios 实例,可以在实例上设置默认配置,以便复用。
- axios.CancelToken.source():创建一个取消令牌源,用于取消请求。
- axios.isCancel(value):检查给定的值是否是由 CancelToken 取消的。
config 常用选项:
headers:设置请求头。用于设置请求发送时携带的头部信息。
示例:
import axios from 'axios'; axios.get('https://api.example.com/data', { headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer token_value' } });
params:URL 查询参数,适用于 GET 请求。它会自动被序列化为查询字符串,并追加到 URL 后面。
示例:
import axios from 'axios'; axios.get('https://api.example.com/data', { params: { userId: 1, page: 2 } }); // 生成的请求 URL 会是 https://api.example.com/data?userId=1&page=2
timeout:请求的超时时间,单位是毫秒。如果请求超过这个时间没有响应,Axios 会中止请求。
示例:
import axios from 'axios'; axios.get('https://api.example.com/data', { timeout: 5000 // 设置超时为5秒 });
auth:设置 HTTP 基本认证凭证,包括 username 和 password。
示例:
import axios from 'axios'; axios.get('https://api.example.com/data', { auth: { username: 'admin', password: '123456' } });
responseType:设置响应的数据类型,常见的值有 json、text、blob、arraybuffer 等。默认是 json。
- json:响应的数据将会被解析为 JSON 格式,适用于返回 JSON 数据的接口。
- text:响应的数据将会被处理为纯文本(string),适用于返回文本数据的接口,如 HTML、纯文本内容等。
- blob:响应的数据会作为 Blob 对象(即二进制大对象)返回,适用于文件下载、图片等二进制数据。
- arraybuffer:响应的数据会作为 ArrayBuffer 对象返回,通常用于二进制数据流,如音频、视频或其他二进制文件。
- document:响应的数据将作为 document 对象返回。通常适用于返回 HTML 文档的接口。
- stream:用于 Node.js 中的请求。stream 使得响应的数据可以作为一个流(stream)处理,通常用于处理大量数据的下载。
示例:
import axios from 'axios'; axios.get('https://api.example.com/data', { responseType: 'blob' });
cancelToken:用于取消请求,提供一个取消令牌,用于在需要时中止请求。
示例:
import axios from 'axios'; const cancelTokenSource = axios.CancelToken.source(); axios.get('https://api.example.com/data', { cancelToken: cancelTokenSource.token }); cancelTokenSource.cancel('请求被用户取消');
withCredentials:是否携带跨域请求时的凭证(如 Cookies)。默认为 false,如果请求跨域且需要凭证,可以设置为 true。
示例:
import axios from 'axios'; axios.get('https://api.example.com/data', { withCredentials: true });
maxRedirects:最大重定向次数,默认情况下 Axios 会自动跟随重定向,设置该参数可以限制最大重定向次数。
示例:
import axios from 'axios'; axios.get('https://api.example.com/redirect', { maxRedirects: 5 });
paramsSerializer:一个函数,用于自定义 URL 查询参数的序列化方式。可以用来定制如何将对象转化为查询字符串。
示例:
import axios from 'axios'; axios.get('https://api.example.com/data', { params: { userId: 1, page: 2 }, paramsSerializer: function (params) { // 使用 URLSearchParams 序列化 const searchParams = new URLSearchParams(params); return searchParams.toString(); } });
发送 GET 请求(axios)
示例:
import axios from 'axios';
// 参数在url后面
axios.get('http://127.0.0.1:8080/test?name=123')
.then(response => {
console.log(response.data); // 输出后台返回的数据
})
.catch(error => {
console.error(error); // 捕获并处理请求中的错误(也可以捕获后台的错误)
});
import axios from 'axios';
// 参数语法上使用params,实际上还是跟在url后面
axios.get('http://127.0.0.1:8080/test', {
params: {
name: 123
}
})
.then(response => {
console.log(response.data); // 输出后台返回的数据
})
.catch(error => {
console.error(error); // 捕获并处理请求中的错误(也可以捕获后台的错误)
});
发送 POST 请求(axios)
示例: 请求头:Content-Type: application/x-www-form-urlencoded
import axios from 'axios';
// 创建 x-www-form-urlencoded 数据格式的对象
const formData = new URLSearchParams();
formData.append('name', 'Tom'); // 请求参数
axios.post('http://127.0.0.1:8080/test', formData, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded' // 不用显式的设置,axios会根据参数的数据类型来选择合适的 Content-Type
}
})
.then(response => {
console.log(response.data); // 输出后台返回的数据
})
.catch(error => {
console.error(error); // 捕获前后台的错误
});
示例: 请求头:Content-Type: application/json
import axios from 'axios';
// 创建 json 对象
const data = {
name: 'Tom'
};
axios.post('http://127.0.0.1:8080/test', data, {
headers: {
'Content-Type': 'application/json' // 不用显式的设置,axios会根据参数的数据类型来选择合适的 Content-Type
}
})
.then(response => {
console.log(response.data); // 输出后台返回的数据
})
.catch(error => {
console.error(error); // 捕获前后台的错误
});
发送 GET 请求(async / await axios)
import axios from 'axios';
// 定义一个异步函数,使用 async/await 语法
async function get() {
try {
// 使用 await 等待 axios.get 请求返回
const response = await axios.get('http://127.0.0.1:8080/test', { params: { 'name': 123 } });
console.log(response.data); // 输出后台返回的数据
} catch (error) {
console.error(error); // 捕获前后台的错误
}
}
// 调用异步函数
get();
发送 POST 请求(async / await axios)
示例: 请求头:Content-Type: application/x-www-form-urlencoded
import axios from 'axios';
// 定义一个异步函数,使用 async/await 语法
async function post() {
try {
// 使用 await 等待 axios.post 请求返回
const response = await axios.post('http://127.0.0.1:8080/test'
, new URLSearchParams({ 'name': 'Tom' }) // 创建 x-www-form-urlencoded 数据格式的对象
);
console.log(response.data); // 输出后台返回的数据
} catch (error) {
console.error(error); // 捕获前端和后端的错误
}
}
// 调用异步函数
post();
示例: 请求头:Content-Type: application/json
import axios from 'axios';
// 定义一个异步函数,使用 async/await 语法
async function post() {
try {
// 使用 await 等待 axios.post 请求返回
const response = await axios.post('http://127.0.0.1:8080/test', { 'name': 'Tom' });
console.log(response.data); // 输出后台返回的数据
} catch (error) {
console.error(error); // 捕获前端和后端的错误
}
}
// 调用异步函数
post();
请求拦截器
请求拦截器(Request Interceptor)允许你在请求被发送到服务器之前,对请求进行修改或添加额外的配置。比如添加认证令牌(token)、设置请求头、统一处理请求参数等。
示例:
import axios from 'axios';
// 请求拦截器
axios.interceptors.request.use(
(config) => {
// 在请求发送前做些什么
// console.log('Request Interceptor:', config);
config.headers['Authorization'] = `Bearer token`; // 在请求头中添加 token
return config; // 必须返回 config,否则请求不会继续
},
(error) => {
// 对请求错误做些什么
console.error('Request Error:', error);
return Promise.reject(error); // 如果发生错误,继续返回 Promise 错误
}
);
async function post() {
try {
const response = await axios.post('http://127.0.0.1:8080/test', { 'name': 'Tom' });
console.log(response.data); // 输出后台返回的数据
} catch (error) {
console.error(error); // 捕获前端和后端的错误
}
}
// 调用异步函数
post();
响应拦截器
响应拦截器(Response Interceptor)是在收到响应之后、响应数据被 then() 或 catch() 处理之前,对响应数据进行处理的一个功能。响应拦截器允许你在响应结果返回到应用之前,统一处理或修改响应的数据或统一异常错误处理。
示例:
import axios from 'axios';
// 响应拦截器
axios.interceptors.response.use(
(response) => {
// console.log('Response Interceptor:', response); // 在响应数据到达应用之前做些什么
// TODO 你可以在这里统一处理数据,例如提取其中需要的部分
console.log("aaaaa", response.data);
return response.data; // 只返回响应的主体部分,去掉多余的信息
},
(error) => {
// 对响应错误做些什么
console.error('Response Error:', error);
// 例如,如果是 401 错误,可以跳转到登录页面
if (error.response && error.response.status === 401) {
window.location.href = '/login';
}
return Promise.reject(error); // 错误处理后,返回拒绝的 Promise
}
);
async function post() {
try {
const data = await axios.post('http://127.0.0.1:8080/test', { 'name': 'Tom' });
console.log(data); // 输出后台返回的数据
} catch (error) {
console.error(error); // 捕获前端和后端的错误
}
}
// 调用异步函数
post();
取消请求
用户可以在页面长时间未返回响应时,点击按钮主动取消请求。前台取消请求后,后台接口仍然还在继续执行(想要后台接口也取消执行,那你需要自定义代码实现,例如再写个取消请求的接口用于前端点击取消是给让前端调用。根据自己的实际情况判断是否需要该需求),只是后续的响应前台不会再处理。axios 也会抛出一个取消的异常供程序员捕获。
示例:
import axios from 'axios';
// 创建一个取消令牌
const CancelToken = axios.CancelToken;
let cancel: (msg?: string) => void; // 用于存储取消函数的变量
async function post() {
try {
const response = await axios.post('http://127.0.0.1:8080/test'
, { 'name': 'Tom' } // 请求参数
, {
cancelToken: new CancelToken(function executor(c) {
cancel = c; // 保存取消函数
})
}
);
console.log(response.data); // 输出后台返回的数据
} catch (error) {
if (axios.isCancel(error)) {
console.log('请求被取消:', error.message); // 如果请求被取消,会进入这个条件
} else {
console.error('请求发生错误:', error); // 其他类型的错误
}
}
}
// 调用异步函数
post();
// 假设在某个地方你需要取消请求,这里使用定时器模拟。实际中应该是一个长时间没有返回响应后的一个取消按钮
setTimeout(() => {
cancel('请求被手动取消'); // 手动取消请求并传递取消的消息
}, 1000); // 1秒后取消请求
中止请求
设置超时时间,当请求超出这个时间限制后,会自动终止请求,并抛出一个超时异常。当然,后台接口依然还是在继续运行。
示例:
import axios from 'axios';
async function post() {
try {
const response = await axios.post('http://127.0.0.1:8080/test'
, { 'name': 'Tom' }
, {
timeout: 5000 // 设置超时时间为 5 秒
}
);
console.log(response.data);
} catch (error: any) {
// 捕获请求超时错误
if (error.code === 'ECONNABORTED') {
console.log('请求超时');
} else {
console.error(error);
}
}
}
// 调用异步函数
post();