在 Node.js 中使用 Fetch API 发出 HTTP 请求

3 min read

Fetch API 是一种受到官方支持的全新方法,用于在 Node.js 中执行 HTTP 请求和检索本地资源。这表示,您的项目不再需要外部 HTTP 客户端依赖项。您现在只需了解如何使用 Node Fetch API,这就是本指南的全部内容。

在本指南中,您将学习以下内容:

  • 什么是 Fetch API
  • Node Fetch API 入门指南
  • 在 Node.js 中使用 Fetch API 发出 HTTP 请求
  • 额外选项和功能

现在就来一探究竟吧!

什么是 Fetch API?

Fetch API 是 JavaScript 接口,用于在本地或通过网络获取资源。具体而言,它提供了全局 fetch() 函数,可以更轻松地执行异步 HTTP 请求。您也可以使用同样的方法来检索本地文件。JavaScript Fetch API 可灵活替代遗留 XMLHttpRequest API。

fetch() 方法基于请求和响应对象。它只需要一个必需参数:您想要获取的资源的本地路径或 URL。此外,它还接受 CORS、HTTP 标头和缓存设置等可选选项 。作为异步方法,fetch() 返回一个 Promise,用于解析服务器生成的响应。此过程由 Response 对象表示,它提供了几种访问和解析其内容正文的方法。

基本的 Fetch API 调用过程如下所示:

fetch("https://httpbin.io/ip", {

  // optional configs...

}).then((response) => {

  // print the JSON response body

  console.log(response.json()) // {  "origin": "<YOUR_IP_ADDRESS>" }

})

Or if you prefer the equivalent async/await syntax, you can write:

const response = await fetch("https://httpbin.io/ip", {

  // optional configs...

})

// print the JSON response body

console.log(await response.json()) // { "origin": "<YOUR_IP_ADDRESS>" }

Node Fetch API 入门指南

多年来,Fetch API 一直受到主流浏览器的支持。然而,Node.js 在2022 年 4 月发布了 18.0.0 版本后,才将其添加到标准 Node.js 库中。具体而言,Node Fetch API 基于 undici 实现。

在 Node.js 18 发布前,您可以将 fetch() 作为实验性功能启用后去使用,或者借助 node-fetch npm 库(另一种常用的 Fetch API 实现)来使用 fetch()。由于 fetch() 现在是 Node.js 官方标准库的一部分,您无需将其导入即可直接在代码中使用。您只需使用以下语法调用 fetch() 方法:

fetch(url, options)

url 为必填项,可以包含:

  • 本地资源(例如 movies.json)的路径
  • 远程端点或资源的 URL(例如 https://httpbin.io/ip 或 https://example.com/movies.json)

options 是可选对象,接受以下可选字段:

  • method:请求的 HTTP 方法,如“GET”、“POST”、“PUT”、“PATCH”和“DELETE”。默认方法为“GET”。
  • headers:Headers 对象或包含要添加到请求中的 HTTP 标头的对象字面量。默认不设置标头。
  • body:包含用作请求正文的数据的对象。请注意,使用 GET 和 HEAD 方法的请求不能有正文。
  • mode:用于请求的模式(例如“cors”、“no-cors”、“same-origin”、“navigate”或“websocket”)。默认设置为 cors。
  • credentials:指定浏览器是否需要发送凭证。必须使用以下任一字符串:“omit”、“same-origin”或“include”。
  • redirect:确定如何处理 HTTP 重定向响应。可以使用“follow”、“error”或“manual”。默认设置为“follow”。
  • referrer:包含请求的反向链接的字符串。默认为空字符串。
  • referrerPolicy:指定用于请求的反向链接政策。
  • signal:AbortSignal 对象实例,支持您使用 AbortController 接口中止请求。
  • priority:字符串,用于指定当前 Fetch 请求相对于其他同类请求的优先级。可以使用“high”、“low”或“auto”。默认设置为“auto”。

查看官方文档中的 fetch() 参数部分,以了解更多信息。

以下是带有 options 对象的 Node.js Fetch 请求示例:

const response = await fetch("https://your-domain.com/api/v1/users", {

  method: "POST",

  credentials: "include",

  headers: {

    "Content-Type": "application/json",

  },

  body: JSON.stringify({

    username: "jane-doe",

    email: "[email protected]"

    role: "superuser",

    age: 23,

    birthplace: "New York",

  }),

})

请注意,正文数据必须与 Content-Type 标头相匹配。

在 Node.js 中使用 Fetch API 发出 HTTP 请求

现在来借助最常用的 HTTP 方法,在真实请求示例中查看 Node Fetch API 的实际运行情况。

GET

您可以通过以下方式使用 Fetch API 执行 GET 请求:

const response = await fetch("https://your-domain.com/your-endpoint")

如您所见,它只需要一行代码。这是因为 fetch() 默认执行 GET 请求。

然后,您可以使用以下任一方法获取响应内容:

  • response.text():返回一个使用以文本为响应正文解析的 Promise。
  • response.json():返回一个使用从 JSON 响应中解析的对象解析的 Promise。
  • response.blob():返回一个使用以 Blob 对象为响应正文解析的 Promise。
  • response.ArrayBuffer():返回一个使用以 ArrayBuffer 实例为响应正文解析的 Promise。
  • response.formData():返回一个使用以 FormData 对象为响应正文解析的 Promise。

完整的代码示例如下所示:

const response = await fetch("https://httpbin.io/ip")

const jsonResponseContent = await response.json() // { "origin": "<YOUR_IP_ADDRESS>" }

const origin = jsonResponseContent.origin // <YOUR_IP_ADDRESS>

如果服务器返回的响应不是 JSON 格式,则 response.json() 指令将会失效并产生 SyntaxError 错误消息。

POST

通过 Node Fetch API 调用发出 POST 请求只需以下几行代码:

const formData = new FormData()

formData.append("username", "serena-smith")

formData.append("email", "[email protected]")

const response = await fetch("https://example.com/api/v1/users", {

  method: "POST",

  body: formData,

})

使用 fetch() 发送 POST 请求的关键是在正文选项中指定要发送至服务器的数据。它可以采用多种格式,包括 JSON、FormData 和文本格式。发送 FormData 对象时,您无需指定 Content-Type 标头。在其他情况下则必须指定。

PUT

使用 Fetch API 执行 PUT 请求与执行 POST 请求相同:

const response = await fetch("https://example.com/api/v1/users", {

  method: "PUT",

  credentials: "include",

  headers: {

    "Content-Type": "application/json",

  },

  body: JSON.stringify({

    username: "john-doe",

    email: "[email protected]"

    role: "regular-user",

    age: 47,

    birthplace: "Chicago",

  }),

})

唯一的区别在于,您需要将“PUT”指定为方法。同样,您也可以通过将方法设置为“PATCH”来发送 PATCH 请求。

DELETE

以下是使用 fetch() 发出 HTTP DELETE 请求的示例:

const response = await fetch("https://example.com/api/v1/users/45", {

  method: "DELETE",

})

同样,关键在于设置正确的 HTTP 方法。其余操作将由 Fetch API 实现来完成。

额外选项和功能

在掌握了如何在常见场景中使用 fetch() 后,您可以开始探索 Node Fetch API 的高级选项了。

设置标头

fetch() 支持通过 options 对象的 headers 字段为请求设置自定义 HTTP 标头。尤其是,headers 接受 Headers 对象或带有特定字符串值的对象字面量。

假设您想在 fetch() 请求中设置 Content-Type 和 User-Agent 标头。您可以使用 Headers 对象,如下所示:

const customHeaders = new Headers()

customHeaders.append("Content-Type", "application/json")

customHeaders.append("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36")

const response = fetch("https://your-domain.com/your-endpoint", {

  headers: customHeaders,

  // other options...

})

同样,您也可以使用对象字面量来设置这些标头:

const response = fetch("https://your-domain.com/your-endpoint", {

  headers: {

    "Content-Type": "application/json",

    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36",

  },

  // other options...

})

该语法结构更紧凑,也更易于阅读。

读取标题

如果您想读取服务器在响应中设置的 HTTP 标头,可按如下方式对其进行访问:

const response = await fetch("https://your-domain.com/your-endpoint", {

  // optional configs...

})

// accessing the "Content-Type" response header

const responseHeaders = response.headers

const responseContentType = response.headers.get("Content-Type")

response.headers 字段返回一个 Headers 对象,您可以使用 get() 方法通过该对象访问特定标头。

Node Fetch API 错误处理

Node.js Fetch API 调用失败可能由以下两种原因造成:

  • AbortError 异常:当请求被 AbortController 强制中止时出现。
  • TypeError 异常:这可能是由于多种原因造成的,如无效的标头名称、无效的 URL 或通用网络错误。查看此文档,了解更多原因。

必须注意,返回 4xx 或 5xx 响应都会被认定为 Fetch API 请求成功完成。换句话说,服务器生成的错误响应不会触发 JavaScript 错误。这种行为的原因在于,fetch() 发出请求后,服务器返回了响应。理论上,以网络角度来看,这不能被视为错误。最终,请求成功结束。

这意味着,您在处理服务器返回的数据之前,应始终检查响应是否成功。为此,您可以实现以下错误处理逻辑:

try {

  const response = await fetch("https://your-domain.com/your-endpoint", {

    // optional configs...

  })

  if (response.ok) {

    // use the data returned by the server...

    // e.g., 

    // await response.json()

  } else {

    // handle 4xx and 5xx errors...

  }

} catch (error) {

  // handle network or abort errors...

}

请注意,响应中的 ok 属性仅在请求成功时才包含 true。

中止 Fetch 请求

Fetch API 支持通过 AbortController API 中止已经发起的请求。

要停止正在进行的 fetch() 请求,您首先需要生成一个 signal 对象,如下所示:

const controller = new AbortController()

const signal = controller.signal

Then, specify it in the options object of your request:

const response = await fetch("https://your-domain.com/your-endpoint", {

  signal: signal,

  // other configs...

})

现在,每当您调用以下指令时,请求都会被 AbortError 中断:

controller.abort()

请记住,服务器可能已经收到请求。在这种情况下,服务器仍会执行请求,但 Node.js 会忽略响应。

恭喜!您现在已经掌握了 Node.js Fetch API 的要领!

结语

在本文中,您学习了什么是 Fetch API 及其在 Node.js 中的用法。具体而言,您首先了解 fetch() 的基础知识,然后深入研究其高级选项和功能。凭借如此强大的 HTTP 客户端,您随时都能轻松检索在线数据。例如,您可以用它来调用我们的 SERP API 端点并开始抓取 SERP 数据。

想要详细了解如何使用 Node.js 抓取数据?请阅读使用 Node.js 进行网页抓取的指南。