JavaScript Fetch API 入门

2025-06-08

JavaScript Fetch API 入门

过去,有两种方式发出请求。一种是使用XMLHttpRequest。另一种是使用 jQuery,即ajax()方法。幸运的是,JavaScript 现在提供了第三种方式——Fetch API。在本教程中,您将学习 JavaScript Fetch API 入门所需的所有知识。

简要介绍

Fetch API 是 JavaScript 标准中新增的 API。它提供了一种更简单、更清晰的服务器请求方式。更棒的是,它基于PromiseXMLHttpRequest实现。这使得它使用起来更简单、更友好。这也是它比 JavaScript和 jQuery 更受欢迎的原因ajax()

JavaScript Fetch API 基础知识

当你想使用 fetch API 发出请求时,你通常需要两样东西。第一个是fetch()方法。这个方法负责发出请求。它需要一个参数,即你想要发出请求的路径或 URL。除了这个参数之外,你还可以通过配置对象来提供这个方法。

此配置对象是可选的。它允许您为请求设置各种设置。例如,您可以添加标头、包含一些数据的正文、设置跨域请求模式、启用缓存、允许或禁止重定向、指定引荐来源网址和 referrerPolicy 等等。您可以在MDN上找到所有可用选项。

// Fetch syntax
fetch(someURL, {})

// or with optional config object
fetch(someURL, {/* settings go here */})

使用承诺处理函数处理获取

您需要的第二件事是Promise 处理函数。正如我们简要讨论过的,fetch API 基于 Promise。这意味着每次您发出请求时,结果(fetch()方法返回的数据)都将是一个 Promise。为了处理这个 Promise,您需要使用其中一个 Promise 处理函数。

您可能最常使用的两个处理函数是then()catch()then()处理函数帮助您处理 Promise 的已实现状态。这适用于已解决和已拒绝的 Promise。处理已拒绝 Promise 的另一种方法是使用catch()

和 都then()可以catch()处理已拒绝的 Promise。但是,只有then()可以处理已解决的 Promise。因此,请确保then()至少使用 来处理 Promise 的已解决状态。对于已拒绝状态,请确定是否要使用then()catch()

当 fetch promise 被 fulfilled 时,它收到的数据会自动传递给附加的处理函数。当你需要处理这些数据时,你必须在这些处理函数内部进行操作。如果你想让这些数据在处理函数外部可用,可以将数据赋值给某个外部变量。

// Use fetch() method with promise handler functions
fetch(someUrl)
  .then(response => {
    // When promise gets resolved
    // log received data to console
    console.log(response)
  })
  .catch(error => {
    // If promise gets rejected
    // log the error to console
    console.log(error)
  })


// Real-world example
fetch('https://sv443.net/jokeapi/v2/joke/Programming')
  // Convert response to JSON format
  .then(response => response.json())
  // Log the response JSON
  .then(jsonData => console.log(jsonData))
  .catch(error => {
    // If promise gets rejected
    // log the error to console
    console.log(error)
  })

// Output:
// {
//   error: false,
//   category: 'Programming',
//   type: 'twopart',
//   setup: 'Programming is like sex.',
//   delivery: 'Make one mistake and you end up supporting it for the rest of your life.',
//   flags: {
//     nsfw: true,
//     religious: false,
//     political: false,
//     racist: false,
//     sexist: false
//   },
//   id: 8,
//   lang: 'en'
// }

如上例所示,你可以将 Promise 处理函数一个接一个地串联起来。建议将函数放在then()最前面,将 放在catch()后面。如果你还使用了finally(),建议将其放在最后。

使用 await 处理 fetch

如果您不想使用 Promise 处理函数,另一个选择是await。它await做两件事。首先,它会暂停周围代码的执行,直到跟在这个关键字后面的 Promise 被满足为止。其次await,它替换了then()函数。它会自动提取 Promise 返回的数据并将其赋值给一个变量。

如果要使用 ,需要记住两点await。首先,请在try...catch语句中使用它。await 是对then()函数的补充,但它并不对 进行补充catch()。如果要捕获可能出现的任何错误,可以使用 catchtry...catch语句。

第二件事是,在顶级 awaitawait发布之前,你只能在异步函数中使用。这就是你能做的。fetch()与 with 一起使用await。然后,用 with 语句包装这两个try...catch,并将其全部放入async函数中。

// Create async function
async function makeRequest() {
  // Use try...catch statement
  try {
    // Use await and make fetch request
    const responseData = await fetch('https://sv443.net/jokeapi/v2/joke/Any')
    // Convert the response to JSON format
    const responseJSON = await responseData.json()

    // Log the converted JSON
    console.log(responseJSON)
  }
  catch (error) {
    // Log any error
    console.log(error)
  }
}

// Call the makeRequest()
makeRequest()
// Output:
// {
//   error: false,
//   category: 'Miscellaneous',
//   type: 'twopart',
//   setup: "Mom asked me where I'm taking her to go out to eat for mother's day.",
//   delivery: 'I told her, "We already have food in the house".',
//   flags: {
//     nsfw: false,
//     religious: false,
//     political: false,
//     racist: false,
//     sexist: false
//   },
//   id: 89,
//   lang: 'en'
// }

处理响应

当你发出请求时,promise 会返回fetch()一个响应对象。该对象包含从服务器接收的信息以及各种方法。我们可以使用这些方法来处理数据。这些方法是clone()redirect()arrayBuffer()formData()blob()text()json()

clone()方法创建响应的克隆。该redirect()方法创建一个新的响应,但使用不同的 URL。该方法arrayBuffer()将响应以ArrayBuffer 的形式返回。该方法将formData()响应以FormData对象的形式返回。该blob()方法将响应以 Blob 的形式返回。

以字符串或文本形式返回text()响应。最后一个方法,即json(),以 JSON 格式返回响应。您应该使用哪种方法来解析响应取决于您期望的数据类型。例如,如果您期望接收 JSON 格式的数据,则使用json(),如果是文本格式,则使用text(),等等。

这些方法的优点在于,您无需知道预期的响应是什么。即使您选择了错误的方法,这些解析响应的方法(例如text()和 )json()通常也能正常工作。例如,假设您使用了text()方法,但响应却是 JSON 格式。

在这种情况下,该text()方法将能够选择该 JSON 并将其解析为字符串。结果基本上是字符串化的 JSON。但是,该方法不适用于文本响应和json()json()需要特定的语法。如果响应是纯文本,并且您使用json(),则会收到语法错误。

因此,如果您不确定应该期望哪种类型的响应,请使用text()。在最坏的情况下,您会得到一些字符串化的 JSON,这样您就知道应该使用json()哪种格式。如果您期望其他格式,请使用相应的方法:response.formData()response.blob()response.arrayBuffer()

// Example no.1:
// Parsing response as a text
async function makeRequest() {
  // Use try...catch statement
  try {
    // Make fetch request
    const responseData = await fetch('https://sv443.net/jokeapi/v2/joke/Programming')

    // Parsing as Text happens here:
    // Parse the response as a text
    const responseText = await responseData.text()

    // Log the text
    console.log(responseText)
  }
  catch (error) {
    // Log any error
    console.log(error)
  }
}

// Call the makeRequest()
makeRequest()
// Output:
// '{
//   error: false,
//   category: 'Programming',
//   type: 'single',
//   joke: 'Programming is 10% science, 20% ingenuity, and 70% getting the ingenuity to work with the science.',
//   flags: {
//     nsfw: false,
//     religious: false,
//     political: false,
//     racist: false,
//     sexist: false
//   },
//   id: 37,
//   lang: 'en'
// }'


// Alternative:
fetch('https://sv443.net/jokeapi/v2/joke/Programming')
  .then(response => response.text())
  .then(responseText => console.log(responseText))
  .catch(err => console.log(err))


// Example no.2:
// Parsing response as a text
async function makeRequest() {
  // Use try...catch statement
  try {
    // Make fetch request
    const responseData = await fetch('https://sv443.net/jokeapi/v2/joke/Programming')

    // Parsing as JSON happens here:
    // Parse the response as a JSON
    const responseJSON = await responseData.json()

    // Log the JSON
    console.log(responseJSON)
  }
  catch (error) {
    // Log any error
    console.log(error)
  }
}

// Call the makeRequest()
makeRequest()
// Output:
// {
//   error: false,
//   category: 'Programming',
//   type: 'twopart',
//   setup: 'How do you generate a random string?',
//   delivery: 'Put a Windows user in front of Vim and tell him to exit.',
//   flags: {
//     nsfw: false,
//     religious: false,
//     political: false,
//     racist: false,
//     sexist: false
//   },
//   id: 129,
//   lang: 'en'
// }


// Alternative:
fetch('https://sv443.net/jokeapi/v2/joke/Programming')
  .then(response => response.json())
  .then(responseJSON => console.log(responseJSON))
  .catch(err => console.log(err))

正在处理已经处理的响应

当您使用一种方法处理响应并将其解析为一种格式时,您无法再次处理它并将其解析为另一种格式。如果您将响应解析为文本,则无法再将其解析为 JSON 格式。解析一次响应后,它将被锁定。再次解析将导致 TypeError。

async function makeRequest() {
  // Use try...catch statement
  try {
    // Make fetch request
    const responseData = await fetch('https://sv443.net/jokeapi/v2/joke/Programming')

    // Parse the response as a text
    const responseText = await responseData.text()

    // This will not work after the first parsing
    // Try to parse the response again as a JSON
    const responseJSON = await responseData.json()

    // Log the text
    console.log(responseText)

    // Log the JSON
    console.log(responseJSON)
  }
  catch (error) {
    // Log any error
    console.log(error)
  }
}

// Call the makeRequest()
makeRequest()
// Output:
// TypeError: Failed to execute 'json' on 'Response': body stream is locked

使用 fetch 发起请求

该方法默认的请求类型fetch()GET。如果您想更改请求类型,可以进行更改。您可以通过可选的配置对象(可将其作为第二个参数传递给该fetch()方法)来更改请求类型。例如,您可以设置methodPOST来发出POST请求,等等。

GET 请求

如果按原样使用该fetch()方法并仅提供 URL,它将自动执行GET请求。

// GET request example
async function makeGetRequest() {
  // Use try...catch statement
  try {
    // Make GET fetch request
    const responseData = await fetch('https://sv443.net/jokeapi/v2/joke/Programming')

    // Parse the response as a JSON
    const responseJSON = await responseData.json()

    // Log the JSON
    console.log(responseJSON)
  }
  catch (error) {
    // Log any error
    console.log(error)
  }
}

// Call the makeGetRequest()
makeGetRequest()
// Output:
// {
//   error: false,
//   category: 'Programming',
//   type: 'single',
//   joke: "Knock knock.
// Who's there?
// Recursion.
// Recursion who?
// Knock knock.",
//   flags: {
//     nsfw: false,
//     religious: false,
//     political: false,
//     racist: false,
//     sexist: false
//   },
//   id: 182,
//   lang: 'en'
// }


// Alternative with promise handler functions:
fetch('https://sv443.net/jokeapi/v2/joke/Programming')
  .then(response => response.json())
  .then(responseJSON => console.log(responseJSON))
  .catch(err => console.log(err))

POST 请求

另一种常见的请求类型是POST。您可以通过更改 on 配置对象来使用 fetch API 发出此类请求method。此对象是您可以传递给 的第二个可选参数fetch()。如果您将 设置method为 ,POSTfetch()方法将执行POST请求。

发出POST请求时,您需要发送一些数据。您可以通过body选项添加这些数据。此选项也包含在配置对象中。此外,您可能还想更改Content-Type。您可以通过headers选项执行此操作。但是,对于简单的请求,POSTmethodbody可能就足够了。

// Some data to send
const userData = {
  firstName: 'Tom',
  lastName: 'Jones',
  email: 'tom@jones.ai'
}

// Make POST request
async function makePostRequest() {
  // Use try...catch statement
  try {
    // Make fetch request
    const responseData = await fetch('/users/register', {
      method: 'POST', // Change the request method
      headers: { // Change the Content-Type
        'Content-Type': 'application/json;charset=utf-8'
      },
      body: JSON.stringify(userData) // Add data you want to send
    })

    // Parse the response as a JSON
    const responseJSON = await responseData.json()

    // Log the JSON
    console.log(responseJSON)
  }
  catch (error) {
    // Log any error
    console.log(error)
  }
}

// Call the makePostRequest()
makePostRequest()


// Alternative with promise handler functions:
fetch('/users/register', {
  method: 'POST', // Change the request method
  headers: { // Change the Content-Type
    'Content-Type': 'application/json;charset=utf-8'
  },
  body: JSON.stringify(userData) // Add data you want to send
})
  .then(response => response.json())
  .then(responseJSON => console.log(responseJSON))
  .catch(err => console.log(err))

DELETE 请求

当您想要删除某些数据、文件等时,可以发出DELETE请求。发出此类请求所需的语法比 略多GET,但比 少POST。您需要做的是将 选项设置method然后,您需要知道正确的 URL 以及要删除的内容。fetch()DELETE

// Make DELETE request
async function makeDeleteRequest() {
  // Use try...catch statement
  try {
    // Make fetch request
    const responseData = await fetch('/users/tom', {
      method: 'DELETE' // Change the request method
    })

    // Parse the response as a JSON
    const responseJSON = await responseData.json()

    // Log the JSON
    console.log(responseJSON)
  }
  catch (error) {
    // Log any error
    console.log(error)
  }
}

// Call the makeRequest()
makeDeleteRequest()


// Alternative with promise handler functions:
fetch('/users/tom', {
  method: 'DELETE', // Change the request method
})
  .then(response => response.text())
  .then(responseText => console.log(responseText))
  .catch(err => console.log(err))

PUT 请求

请求类型PUT最常用于更新现有数据或资源。此请求看起来与 几乎相同POST。主要(有时也是唯一的)区别在于method的选项fetch()必须设置为PUT

// Some data to send to update existing records
const userData = {
  firstName: 'Jack',
  lastName: 'O\'Brian',
  email: 'jack@obrian.co'
}

// Make Put request
async function makePutRequest() {
  // Use try...catch statement
  try {
    // Make fetch request
    const responseData = await fetch('/users/jack', {
      method: 'PUT', // Change the request method
      body: JSON.stringify(userData) // Add data you want to send
    })

    // Parse the response as a JSON
    const responseJSON = await responseData.json()

    // Log the JSON
    console.log(responseJSON)
  }
  catch (error) {
    // Log any error
    console.log(error)
  }
}

// Call the makePutRequest()
makePutRequest()


// Alternative with promise handler functions:
fetch('/users/jack', {
  method: 'PUT', // Change the request method
  body: JSON.stringify(userData) // Add data you want to send
})
  .then(response => response.json())
  .then(responseJSON => console.log(responseJSON))
  .catch(err => console.log(err))

PATCH 请求

PATCH是我们将要讨论的最后一种使用 fetch API 的请求类型。这种请求与 非常相似PUT。两者的区别在于PUT用于用新版本更新旧版本。这意味着您可以更新所有内容。而PATCH则仅更新部分现有数据,例如用户电子邮件地址。

// Some data to send to update
// only a part of existing records
const userData = {
  email: 'jack@obrian.co'
}

// Make PATCH request
async function makePatchRequest() {
  // Use try...catch statement
  try {
    // Make fetch request
    const responseData = await fetch('/users/jack', {
      method: 'PATCH', // Change the request method
      body: JSON.stringify(userData) // Add data you want to send
    })

    // Parse the response as a JSON
    const responseJSON = await responseData.json()

    // Log the JSON
    console.log(responseJSON)
  }
  catch (error) {
    // Log any error
    console.log(error)
  }
}

// Call the makePatchRequest()
makePatchRequest()


// Alternative with promise handler functions:
fetch('/users/jack', {
  method: 'PATCH', // Change the request method
  body: JSON.stringify(userData) // Add data you want to send
})
  .then(response => response.json())
  .then(responseJSON => console.log(responseJSON))
  .catch(err => console.log(err))

关于 Response 对象的说明

我们简要讨论了 Response 对象上可以使用的方法:text()json()formData()blob()。这些方法并非 Response 对象的全部。它还包含许多属性。您可能会发现其中一些属性很有用arrayBuffer()clone()redirect()

一些最有用的属性是statusTextstatusokstatusText是包含 HTTP 状态代码消息的字符串。status是一个数字,用于指定响应的状态代码。当您发出请求并成功时,它将具有status200 的值。

ok一个布尔值,指定 是否status在 200 到 299 的代码范围内。因此,如果您的请求成功,即 200, 的值ok将为true。此外,还有一个body属性。此属性包含您收到的数据。当您使用某些方法解析响应时,它会与此body属性配合使用。

// Make fetch request
fetch('https://sv443.net/jokeapi/v2/joke/Programming')
  .then(response => console.log(response)) // Log the Response object
  .catch(err => console.log(err))

// Output:
// {
//   body: (...)
//   bodyUsed: false
//   headers: Headers
//   ok: true
//   redirected: false
//   status: 200
//   statusText: ""
//   type: "cors"
//   url: "https://sv443.net/jokeapi/v2/joke/Programming"
// }

结论:JavaScript Fetch API 入门

JavaScript Fetch API 提供了一种简单易用的请求方式。希望本教程能帮助您了解 Fetch API 是什么以及它的工作原理。也希望我们之前的示例能帮助您理解如何使用这个 API,以及如何成功发出请求以及如何正确处理响应。

鏂囩珷鏉ユ簮锛�https://dev.to/alexdevero/getting-started-with-the-javascript-fetch-api-373k
PREV
如何创建自己的 React 自定义 Hooks
NEXT
React useCallback Hook 快速指南