JavaScript Fetch API

摘要:在本教程中,您将了解 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/awaitfetch() 方法一起使用,以使代码更清晰

const response = await fetch(url);
const data = await response.json();
console.log(data); // json dataCode language: JavaScript (javascript)

除了 json() 方法外,Response 对象还具有其他方法,如 text()blob()formData()arrayBuffer(),用于处理相应的数据类型。

处理 HTTP 状态码

Response 对象具有一个 status 属性,该属性提供响应的 HTTP 状态码

response.statusCode 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/usersCode 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/usersCode language: JavaScript (javascript)

(将 .com 更改为 .net),然后打开 index.html 文件。页面将显示以下错误消息

Error getting usersCode language: JavaScript (javascript)

控制台窗口将显示以下错误

GET https://jsonplaceholder.typicode.net/users net::ERR_NAME_NOT_RESOLVEDCode 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 secondsCode language: JavaScript (javascript)

下载项目源代码

单击此处下载项目源代码

发出 HTTP POST 请求

我们将向以下 API 端点发出 HTTP POST 请求,该端点使用 titlebodyuserId 创建一个新的博客文章

<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 对象具有 titlebodyuserId 属性。

第五,使用 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)

最后,使用包含 titlebodyuserId 属性的博客文章对象调用 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. 打开控制台窗口,如果请求成功,您将看到以下消息

javascript fetch api post method

下载项目源代码

单击此处下载项目源代码

摘要

  • XMLHttpRequest 对象相比,Fetch API 提供了一种更简单、更灵活的方式发出 HTTP 请求。
  • 使用 fetch() 方法向 URL 发出异步 Web 请求。
  • fetch() 返回一个 Promise,该 Promise 解析为 Response 对象。
  • 使用 Response 对象的 statusok 属性来检查请求是否成功。
  • 使用 Response 对象的 json() 方法将内容解析为 JSON 数据。
  • 使用 try...catch 语句处理发出 HTTP 请求时的错误。
本教程是否有用?