in

如何使用 Fetch API 在 Node.js 中进行 HTTP 请求

如何使用 Fetch API 在 Node.js 中进行 HTTP 请求

大多数的网络通信都是通过 HTTP 请求实现的。浏览器将它们发送到服务器以获取要显示的信息,服务器之间也使用它们进行通信。

因此,对 HTTP 请求的了解是任何 web 开发者都应具备的宝贵技能。

在本文中,您将学习 Node.js 中最常用的 HTTP 请求方法之一:Fetch API。

我们将回答以下问题:

  • 如何使用 Fetch API?
  • 如何使用 Fetch API 发送 POST 请求?
  • 如何在 Fetch API 中访问响应状态码?
  • Fetch API 和 Axios 谁会在战斗中胜出?
  • 可以使用代理与 Fetch API 一起工作吗?

什么是 Fetch API?

Fetch API 是一个基于承诺的接口,用于向服务器发出 HTTP 请求。

它是一个简单的方式,用于从服务器获取资源,而不需要使用任何额外的 JavaScript 库。该 API 在所有主要浏览器和 Node.js 版本中都可用,从 Node 18 开始。

如何在 Node.js 中使用 Fetch API?
在本文的这一部分,您将学习如何使用 Fetch API 及其提供的各种功能。

设置

要在 Node.js 中原生使用 Fetch API,您需要一个 Node 版本为 18 或更高的版本。

您可以使用 node -v 命令检查当前的 Node 版本。如果它低于 18,请按照官方说明更新它,然后再按照教程进行操作。

您还需要创建一个新的 Node.js 项目来跟随代码示例。为此,创建一个名为 fetch_example 的新文件夹,移动到该文件夹中,并在终端中运行 npm init。使用安装程序提供的默认值。

安装完成后,在 package.json 文件中添加以下内容:

"type": "module".


// [ …]
  "description": "",
  "type": "module"
}

现在你已经准备好学习更多关于Fetch API的知识了!

fetch() 函数

Fetch API 的基础是 fetch() 函数。给定一个请求,它将返回一个承诺,承诺将在某个时候从服务器返回响应。然后,您可以使用 .then() 语法在承诺上链式调用函数。

让我们看看如何使用 Fetch 从 DummyJSON 引用 API 请求数据。

在下面的代码示例中,我们从服务器请求所有引用,然后使用 .json() 将响应从字符串转换为 JS 对象,然后在控制台中打印每个引用。

要尝试一下,请将以下代码粘贴到 index.js 文件中,并使用 node index.js 运行它。

fetch('https://dummyjson.com/quotes')
  .then((response) => response.json())
  .then((response) => response.json())
  .then((json) => {
    json.quotes.forEach(quote => console.log(`${quote.quote} -- ${quote.author}`));
  });

下面是它返回的输出:

Life isn’t about getting and having, it’s about giving and being. -- Kevin Kruse
Whatever the mind of man can conceive and believe, it can achieve. -- Napoleon Hill
Strive not to be a success, but rather to be of value. -- Albert Einstein
...

你也可以使用 Fetch API 请求 HTML 页面。但由于它没有内置的工具来解析内容,您需要使用像 Cheerio 或 node-html-parser 这样的库,从 HTML 中提取所需的数据。

异常处理(HTTP状态码)

如果你尝试使用fetch()获取一个拼写错误的URL,会发生什么呢?

fetch('https://dummyjson.com/quotess')
  .then((response) => response.json())
  .then((json) => {
    json.quotes.forEach(quote => console.log(`${quote.quote} -- ${quote.author}`));
  });

哦,不,一个错误!

SyntaxError: Unexpected token o in JSON at position 1
    at JSON.parse (<anonymous>)

错误发生的原因是服务器没有返回 JSON,而是返回了一个 404 页面——这是你在互联网上肯定遇到过的情况。虽然这是一个有效的响应,但 JSON 解析器无法解析该页面。

由于它是一个承诺,你可以尝试使用 .catch() 方法来处理错误。

fetch('https://dummyjson.com/quotess')
  .then((response) => response.json())
  .then((json) => {
    json.quotes.forEach(quote => console.log(`${quote.quote} -- ${quote.author}`));
  })
  .catch((error) => console.log(`There's a problem: ${error}`));

它将导致打印以下内容:

There's a problem: SyntaxError: Unexpected token o in JSON at position 1

程序现在不会崩溃,但错误信息对于调试来说相当不清晰。问题在于 .fetch() 只有在资源无法访问时才会失败,而不是在返回 404 时失败。

为了解决这样的问题,你可以在处理响应之前检查响应的状态码。如果是 200,响应应该是预期的。如果是 404,说明 URL 是无效的。除此之外,还有许多其他的状态码

在 Fetch API 中,你可以通过读取响应的 .ok 属性来简单地实现这一点。如果响应的状态码是 200,它将为 true,否则为 false。

如果状态码不是 200,你可以使用 Promise.reject() 来引发一个错误,这个错误将被 .catch() 方法捕获。

以下是一个正确处理错误的代码示例:

fetch('https://dummyjson.com/quotess')
  .then((response) => {
    if (response.ok) {
      return response.json()
    } return Promise.reject("Status code not 200.")
  })
  .then((json) => {
    json.quotes.forEach(quote => console.log(`${quote.quote} -- ${quote.author}`));
  })
  .catch((error) => console.log(`There's a problem: ${error}`));

对于遇到问题的URL,这将返回以下内容,

There's a problem: Status code not 200.

发送 POST 请求

到目前为止,你只发送了 GET 请求——这些 HTTP 请求用于请求某个资源的内容。

还有一些其他类型的请求,比如 PUT、POST、DELETE 等。这些请求可以让你提交更改服务器上资源的请求,而不仅仅是返回它们。

你也可以使用 Fetch API 发送这些请求。

例如,假设你有一个任务需要提交到 DummyJSON 的 todo API

let todo = {
  todo: "Learn how to send POST requests with Fetch API",
  completed: false,
  userId: 26,
}

你可以向 fetch() 方法提供一个对象,带有请求的附加参数。在这种情况下,你需要提供:

  • 你想使用的 HTTP 方法(POST);
  • 表示内容类型的头部:JSON;
  • 你想附加到请求中的主体(将 todo 转换为 JSON 字符串)。

以下是一个 POST 请求的示例:

fetch('https://dummyjson.com/todos/add', {
  method: "POST",
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(todo)
})
  .then((response) => response.text())
  .then((data) => console.log(data))

服务器会响应你刚刚添加的项目。控制台将打印出该项目。由于这是一个模拟 API,发送额外的项目不会更新数据库,但对于真实的 API 来说,这应该是可行的。


如何在 Fetch API 中使用代理?

在发送 HTTP 请求时,有时你会希望使用代理来隐藏你的 IP 地址。这在你使用 Node.js 进行网页抓取时非常有用,但在你想要隐藏 API 使用情况时也同样适用。

代理充当你的请求和请求接收者之间的中间人,将请求的原始 IP 更改为代理的 IP。这样,服务器就无法知道是你在请求信息。

不幸的是,浏览器原生的 Fetch API 不支持代理。默认情况下,Node 中的 fetch() 函数也无法使用代理。

对此有一个解决方法,但需要两个库:node-fetchhttps-proxy-agent

首先,在终端中使用 npm install 命令安装这些库。

npm install node-fetch
npm install https-proxy-agent

然后在正在使用的JavaScript文件的顶部导入它们

import fetch from 'node-fetch'
import HttpsProxyAgent from 'https-proxy-agent';

之后,你需要获取你的代理链接并将其注册为环境变量。

在本文中,我们将使用IPRoyal 住宅代理。它们提供了一种便宜且简单的方法,通过真实的 IP 地址路由请求,每次请求都会更改,从而隐藏你的 IP。

如果你也在使用 IPRoyal,你可以在客户端区域的仪表板中找到你的代理链接。

IPRoyal residential proxies dashboard

使用终端中的export方法将其注册为环境变量。

export HTTPS_PROXY=http://link-to-your-proxy.com

然后,你可以在 API 调用中使用代理,通过提供一个包含由 http-proxy-agent 创建的新代理代理对象的 agent 属性。

fetch('https://ipv4.icanhazip.com', {
  agent: new HttpsProxyAgent.HttpsProxyAgent(process.env.HTTPS_PROXY),
})
  .then((response) => response.text())
  .then((data) => console.log(data))

你可以通过 process.env.HTTPS_PROXY 从环境中访问代理链接。这将确保代理链接(可能仅供私人使用)在你与他人分享代码时不会泄露。


Fetch API 与 Axios

一个在 Node.js 中进行 GET 和 POST 请求的流行包是 Axios,它提供了类似于 Fetch API 的基于承诺的接口。

对于基本的用例,Axios 和 Fetch API 都提供了一组类似的功能。语法也相同,除了少数属性名称的差异。

这两个库的一个明显区别是,Fetch API 不需要安装:它是浏览器和 Node.js 的原生 API。

第二个区别是,Axios 可以在不运行转换函数的情况下处理 JSON。你可以像访问本地 JavaScript 对象一样访问 response.data 的参数。这非常方便。

以下是一个使用 Axios 的 GET 请求示例(你需要使用 npm install axios 安装库才能运行代码示例):

import axios from 'axios';

axios.get('https://dummyjson.com/quotes')
  .then((response) => {
    response.data.quotes.forEach(quote => console.log(`${quote.quote} -- ${quote.author}`));
  });

下面是一个POST请求示例:

import axios from 'axios';

let todo = {
  todo: "Learn how to send POST requests with Fetch API",
  completed: false,
  userId: 26,
}

axios.post('https://dummyjson.com/todos/add', todo)
  .then((response) => { console.log(response.data) });

Fetch API 是在脚本和小项目中进行一次性请求的不错选择,而 Axios 更适合专门的项目。


常见问题解答

ReferenceError: fetch is not defined

这个错误意味着你没有使用足够新的 Node.js 版本,其中没有可用的原生 Fetch API 接口。要解决这个问题,你需要更新你的 Node.js 版本或使用提供该功能的 node-fetch 库。

TypeError: fetch failed – cause: ConnectTimeoutError: Connect Timeout Error

如果连接网站时出现超时,这个错误就会发生。检查你是否已连接到互联网,以及请求中是否有会花费很长时间的内容,例如速度慢的免费代理服务器。

TypeError: fetch failed – cause: Error: getaddrinfo ENOTFOUND http

如果找不到 URL,这个错误就会发生。检查你使用的 URL 是否正确。在某些情况下,你可能会自然地遇到这样的 URL,例如在进行网页抓取时。在这种情况下,通过 .catch() 处理它们以避免中止整个程序是很重要的。


结    论

使用 Fetch API,你可以轻松地在 Node.js 中发出 HTTP 请求,而无需安装任何额外的包。

在本文中,你学习了如何在 Node.js 中使用 Fetch API 发送 GET 和 POST 请求,以及检查响应的状态码。你还了解了如何使用代理在请求时隐藏你的真实 IP 地址,以及 Fetch API 和 Axios 之间的区别。

为了更多地练习该 API,我们建议尝试从互联网上众多免费的 JSON API 请求信息。或者,你可以构建一个网页抓取项目,使用像 node-html-parser 这样的库请求 HTML 并提取必要的信息。

Written by 河小马

河小马是一位杰出的数字营销行业领袖,广告中国论坛的重要成员,其专业技能涵盖了PPC广告、域名停放、网站开发、联盟营销以及跨境电商咨询等多个领域。作为一位资深程序开发者,他不仅具备强大的技术能力,而且在出海网络营销方面拥有超过13年的经验。