摘要:在本教程中,您将了解 JavaScript Fetch API 以及如何使用它来进行异步 HTTP 请求。
JavaScript Fetch API 简介
Fetch API 是一个强大而现代的工具,它简化了直接从 Web 浏览器发出 HTTP 请求的过程。
如果您以前使用过 XMLHttpRequest
对象,您会发现 Fetch API 可以处理所有相同的任务,但更加优雅且简便。
Fetch API 利用了 Promise,提供了一种更简洁、更灵活的方式与服务器交互。它有助于更直观地处理异步请求和响应。
fetch()
是 全局 window 对象 的一个方法,它允许您使用单个命令向 URL 发送 HTTP 请求。无论您是检索数据、提交表单还是与 API 交互,Fetch API 都可以帮助简化整个过程,使您的代码更具可读性。
发送请求
fetch()
仅需要一个参数,即您要获取的资源的 URL
fetch(url);
Code language: JavaScript (javascript)
fetch()
方法返回一个 Promise
,因此您可以使用 then()
和 catch()
方法来处理它
fetch(url)
.then(response => {
// handle the response
})
.catch(error => {
// handle the error
});
Code language: JavaScript (javascript)
请求完成后,资源将变为可用,并且 Promise
将解析为 Response
对象。
Response
对象充当获取资源的 API 包装器。
读取响应
如果响应包含 JSON 数据,您可以使用 Response
对象的 json()
方法来解析它。
json()
方法返回一个 Promise
,该 Promise
解析为获取资源的完整内容,允许访问 JSON 数据
fetch(url)
.then(response => response.json())
.then(data => console.log(data));
Code language: JavaScript (javascript)
在实践中,您通常将 async
/await
与 fetch()
方法一起使用,以使代码更清晰
const response = await fetch(url);
const data = await response.json();
console.log(data); // json data
Code language: JavaScript (javascript)
除了 json()
方法外,Response
对象还具有其他方法,如 text()
、blob()
、formData()
和 arrayBuffer()
,用于处理相应的数据类型。
处理 HTTP 状态码
Response
对象具有一个 status
属性,该属性提供响应的 HTTP 状态码
response.status
Code language: JavaScript (javascript)
HTTP 状态码允许您确定请求是否成功
const response = await fetch(url);
if (response.status === 200) {
// success
}
Code language: JavaScript (javascript)
在实践中,您将使用一个方便的属性 ok
来检查状态码是否在 200-299 范围内。如果为 false
,则请求未成功
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
Code language: JavaScript (javascript)
JavaScript Fetch API 示例
我们将向以下 API 端点发出 GET 请求,该端点返回用户列表
https://jsonplaceholder.typicode.com/users
Code language: JavaScript (javascript)
步骤 1. 创建一个新目录(例如 fetch)来存储项目文件。
步骤 2. 在项目目录中创建一个 index.html
文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Fetch API Demo</title>
<script src="js/app.js" defer></script>
</head>
<body>
<div id="root">
<div id="content"></div>
<p id="message"></p>
<p id="loading"></p>
</div>
</body>
</html>
Code language: HTML, XML (xml)
HTML 文件具有包含三个元素的根元素
#content
用于渲染用户列表。#message
用于显示任何错误消息。#loading
用于显示加载消息。
步骤 3. 在 js
目录中创建一个 app.js
const getUsers = async () => {
const url = 'https://jsonplaceholder.typicode.com/users';
const response = await fetch(url);
return await response.json();
};
const render = (users) => {
return users.map(({ name, email }) => `<li>${name} (${email})</li>`).join('');
};
(async () => {
const users = await getUsers();
document.querySelector('#content').innerHTML = `<ul>${render(users)}</ul>`;
})();
Code language: JavaScript (javascript)
工作原理。
首先,定义一个函数 getUsers
,它使用 fetch()
方法从 API 端点获取数据:https://jsonplaceholder.typicode.com/users
const getUsers = async () => {
const url = 'https://jsonplaceholder.typicode.com/users';
const response = await fetch(url);
return await response.json();
};
Code language: JavaScript (javascript)
其次,创建一个新函数 render
,它返回一个 HTML 代码片段,用于在屏幕上显示用户列表
const render = (users) => {
return users.map(({ name, email }) => `<li>${name} (${email})</li>`).join('');
};
Code language: JavaScript (javascript)
第三,定义一个 IIFE 函数,它调用 getUsers()
函数并在屏幕上显示用户列表
(async () => {
const users = await getUsers();
document.querySelector('#content').innerHTML = `<ul>${render(users)}</ul>`;
})();
Code language: JavaScript (javascript)
处理错误
在发出 Web 请求时,可能会发生各种错误,例如网络中断、服务器停机或其他连接问题。
要处理错误,可以使用 try...catch
语句
(async () => {
try {
// fetch the users
const users = await getUsers();
// show the user list
document.querySelector('#content').innerHTML = `<ul>${render(users)}</ul>`;
} catch (err) {
// show the error message
document.querySelector('#message').textContent = err.message;
}
})();
Code language: JavaScript (javascript)
在此示例中,如果发生错误,catch
块将执行,在控制台中记录错误消息,并向用户显示用户友好的错误消息。
要测试此功能,可以将 API 端点更改为无效 URL,例如
https://jsonplaceholder.typicode.net/users
Code language: JavaScript (javascript)
(将 .com
更改为 .net
),然后打开 index.html 文件。页面将显示以下错误消息
Error getting users
Code language: JavaScript (javascript)
控制台窗口将显示以下错误
GET https://jsonplaceholder.typicode.net/users net::ERR_NAME_NOT_RESOLVED
Code language: JavaScript (javascript)
显示加载指示器
如果网络速度较慢,您会看到空白页面短暂出现,这会导致用户体验不佳。
要改进这一点,您可以在获取数据时显示加载消息。
为此,您可以修改 IIFE 函数,如下所示
(async () => {
// show the loading element
const loadingElem = document.querySelector('#loading');
loadingElem.innerHTML = 'Loading...';
try {
// fetch the users
const users = await getUsers();
// show the user list
document.querySelector('#content').innerHTML = `<ul>${render(users)}</ul>`;
} catch (err) {
// show the error message
document.querySelector('#message').textContent = err.message;
} finally {
loadingElem.innerHTML = '';
}
})();
Code language: JavaScript (javascript)
在发出请求之前,我们将加载消息设置为 'Loading...'
const loadingElem = document.querySelector('#loading');
loadingElem.innerHTML = 'Loading...';
Code language: JavaScript (javascript)
请求完成后,无论成功与否,您都会在 finally
块中将加载消息清除为空白
// ...
finally {
loadingElem.innerHTML = '';
}
Code language: JavaScript (javascript)
请记住,如果网络速度足够快,加载消息可能不可见。要测试加载消息,可以模拟网络延迟,如下所示
(async () => {
// show the loading element
const loadingElem = document.querySelector('#loading');
loadingElem.innerHTML = 'Loading...';
// simulate network delay
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
await delay(2000); // delay 2 seconds
try {
// fetch the users
const users = await getUsers();
// show the user list
document.querySelector('#content').innerHTML = `<ul>${render(users)}</ul>`;
} catch (err) {
// show the error message
document.querySelector('#message').textContent = err.message;
} finally {
loadingElem.innerHTML = '';
}
})();
Code language: JavaScript (javascript)
在此代码中,我们包含以下代码段,在发出请求之前引入 2 秒延迟
// simulate network delay
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
await delay(2000); // delay 2 seconds
Code language: JavaScript (javascript)
下载项目源代码
发出 HTTP POST 请求
我们将向以下 API 端点发出 HTTP POST 请求,该端点使用 title
、body
和 userId
创建一个新的博客文章
<code>https://jsonplaceholder.typicode.com/posts</code>
Code language: HTML, XML (xml)
步骤 1. 创建一个新目录来存储项目文件。
步骤 2. 在项目目录中创建一个新的 index.html
文件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Fetch API Demo - HTTP POST</title>
<meta name="robots" content="noindex">
<script src="js/app.js" defer></script>
</head>
<body>
</body>
</html>
Code language: HTML, XML (xml)
index.html
文件在其标头中包含 js/app.js
文件。
步骤 3. 使用以下代码创建一个新的 js/app.js
文件
async function create(blogPost) {
try {
// Create the URL
const url = 'https://jsonplaceholder.typicode.com/posts';
// Create the headers
const headers = {
'Content-Type': 'application/json',
};
// Create the POST body
const body = JSON.stringify({
title: blogPost.title,
body: blogPost.body,
userId: blogPost.userId,
});
// Send the POST request
const response = await fetch(url, { method: 'POST', headers, body });
// Check the response status
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
// Parse the JSON response
const data = await response.json();
console.log('Success:', data);
} catch (error) {
// Handle any errors
console.error('Error:', error);
}
}
create({
title: 'Test Post',
body: 'This is a test post',
userId: 1,
});
Code language: JavaScript (javascript)
工作原理。
首先,定义一个函数,它创建一个接受帖子对象的新博客文章
async function create(post)
Code language: JavaScript (javascript)
其次,构造一个 URL 端点,将向该端点发送 POST 请求
const url = 'https://jsonplaceholder.typicode.com/posts';
Code language: JavaScript (javascript)
第三,创建一个将与请求一起发送的 HTTP 标头
const headers = {
'Content-Type': 'application/json',
};
Code language: JavaScript (javascript)
将 'Content-Type'
标头设置为 'application/json'
,以指示请求的正文采用 JSON 格式。
第四,使用 JSON.stringify()
方法将帖子对象序列化为 JSON 字符串,从而创建 POST 请求的正文
const body = JSON.stringify({
title: post.title,
body: post.body,
userId: post.userId,
});
Code language: JavaScript (javascript)
这假设 blogPost
对象具有 title
、body
和 userId
属性。
第五,使用 fetch()
方法发送 POST 请求
const response = await fetch(url, {
method: 'POST',
headers,
body
});
Code language: JavaScript (javascript)
在此语法中
url
:您发送 POST 请求的 API 端点。method: 'POST'
:指定这是一个 HTTP POST 请求。headers
:包含请求中的标头。body
:包含 HTTP POST 请求正文中包含的 JSON 字符串。
fetch()
方法返回一个 Response
对象。
第六,检查响应状态,如果请求未成功,则抛出错误
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
Code language: JavaScript (javascript)
第七,解析 JSON 响应并将数据记录到控制台窗口
const data = await response.json();
console.log('Success:', data);
Code language: JavaScript (javascript)
第八,捕获请求期间发生的任何错误并将其记录到控制台
catch (error) {
console.error('Error:', error);
}
Code language: JavaScript (javascript)
最后,使用包含 title
、body
和 userId
属性的博客文章对象调用 create()
函数
create({
title: 'Test Post',
body: 'This is a test post',
userId: 1,
});
Code language: JavaScript (javascript)
步骤 4. 在 Web 浏览器中打开 index.html。它将执行发出 HTTP POST 请求的 app.js 文件。
步骤 5. 打开控制台窗口,如果请求成功,您将看到以下消息

下载项目源代码
摘要
- 与
XMLHttpRequest
对象相比,Fetch API 提供了一种更简单、更灵活的方式发出 HTTP 请求。 - 使用
fetch()
方法向 URL 发出异步 Web 请求。 fetch()
返回一个Promise
,该Promise
解析为Response
对象。- 使用
Response
对象的status
或ok
属性来检查请求是否成功。 - 使用
Response
对象的json()
方法将内容解析为 JSON 数据。 - 使用
try...catch
语句处理发出 HTTP 请求时的错误。