Skip to content

AJAX 请求

在浏览器中进行异步 HTTP 请求的现代标准是 Fetch API。它提供了比旧的 XMLHttpRequest 更强大、更灵活的接口。

fetch() 最简单的用法只需提供你想获取的资源的 URL。默认情况下,这会执行一个 GET 请求。

fetch('https://api.example.com/users') // 资源的 URL
.then(response => {
// 检查响应是否成功(状态码 200-299)
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return response.json(); // 将响应体解析为 JSON
})
.then(data => {
console.log('Data received:', data);
// 处理接收到的数据
})
.catch(error => {
console.error('Fetch error:', error);
// 处理错误(网络问题、解析错误等)
});

fetch() 返回一个 Promise,该 Promise 解析为表示请求响应的 Response 对象。然后你可以在 Response 对象上使用 .json() 或 .text() 等方法来访问实际数据,这些方法同样返回 Promise。

要自定义请求(例如,使用 POST、发送数据、设置头部),可以将一个选项对象作为 fetch() 的第二个参数传入。

选项描述
methodHTTP 请求方法(例如:‘GET’、‘POST’、‘PUT’、‘DELETE’、‘PATCH’)。默认为 ‘GET’。
headers一个对象或 Headers 实例,包含请求头部(例如:{'Content-Type': 'application/json'})。
body请求体。可以是字符串、Blob、BufferSource、FormData、URLSearchParams 或 ReadableStream。必须与 Content-Type 头部匹配。
mode控制是否允许跨域请求(例如:‘cors’、‘no-cors’、‘same-origin’)。默认为 ‘cors’。
cache控制请求如何与浏览器 HTTP 缓存交互(例如:‘default’、‘no-store’、‘reload’)。
credentials控制是否随跨域请求发送 Cookie(‘include’、‘same-origin’、‘omit’)。

选择使用 GET 还是 POST 取决于你想要执行的操作:

  • GET:用于检索数据。请求可以被缓存、收藏,并保留在浏览器历史记录中。数据通过 URL 发送。
  • POST:用于提交创建或更新资源的数据。请求默认不缓存,不保留在浏览器历史记录中,并且对数据长度没有限制。数据通过请求体发送。

在以下情况始终使用 POST:

  • 请求修改服务器上的数据(创建、更新、删除)。
  • 发送敏感信息(如密码)。
  • 发送大量数据。
  • 发送二进制数据。

要通过 GET 发送数据,将其作为查询参数附加到 URL。你可以使用 URLSearchParams 安全地构建查询字符串。

const params = new URLSearchParams({
userId: '123',
limit: 10
});
fetch(`https://api.example.com/posts?${params}`)
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));

添加随机参数 (?_=${Date.now()}) 通常不是防止缓存的现代方法。如果需要,应在服务器响应中使用适当的 Cache-Control 头部,并在 fetch 请求中使用 cache 选项。

要使用 POST 发送 JSON 数据,将你的 JavaScript 对象字符串化,并将 Content-Type 头部设置为 application/json。

const userData = {
name: 'John Doe',
email: 'john.doe@example.com'
};
fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
// 如有需要,添加其他头部,例如 Authorization
// 'Authorization': 'Bearer YOUR_API_TOKEN'
},
body: JSON.stringify(userData) // 将 JS 对象转换为 JSON 字符串
})
.then(response => {
if (!response.ok) {
// 如果服务器返回错误状态,解析可能的 JSON 错误消息
return response.json().then(errData => {
throw new Error(errData.message || `HTTP error! Status: ${response.status}`);
});
}
// 在解析 JSON 之前检查响应是否有内容
const contentType = response.headers.get('content-type');
if (contentType && contentType.includes('application/json')) {
return response.json(); // 创建成功,可能返回新的用户对象
} else {
return {}; // 或者处理非 JSON 成功响应(例如:状态码 201/204)
}
})
.then(data => {
console.log('Success:', data);
// 处理成功创建(例如:显示成功消息)
})
.catch(error => {
console.error('Error posting data:', error);
// 向用户显示错误消息
});

你可以轻松地使用 FormData 对象发送 HTML 表单中的数据。使用 FormData 时,Fetch 会自动设置正确的 Content-Type(multipart/form-data)。

const myForm = document.getElementById('myFormElement');
myForm.addEventListener('submit', function(event) {
event.preventDefault(); // 阻止默认表单提交
const formData = new FormData(myForm);
// 如果需要,可以附加额外数据:
// formData.append('extraField', 'extraValue');
fetch('/submit-form', {
method: 'POST',
body: formData
// 不需要 Content-Type 头部;浏览器会为 FormData 自动设置
})
.then(response => response.json()) // 假设服务器返回 JSON
.then(data => console.log('Form submission successful:', data))
.catch(error => console.error('Form submission error:', error));
});

fetch 的第一个参数通常是服务器端点 (API) 的 URL。此端点设计用于接收请求、处理请求(例如,与数据库交互、执行计算),并发送回响应。

此端点可以托管在与你的网页相同的服务器上,也可以托管在不同的服务器上(需要正确的 CORS 配置)。

Fetch 本质上是异步的,并且基于 Promise。这意味着:

  • JavaScript 执行不会等待请求完成。
  • 浏览器保持响应,允许用户与页面交互。
  • 你在 Promise 解析时处理响应(使用 .then() 或 await)。

同步请求(使用 async=false 的 XMLHttpRequest)不应使用。它们会阻塞浏览器的主要线程,导致用户界面冻结,用户体验极差。现代 Web 开发完全依赖于异步模式。