in

如何在Node.js中使用Fetch API发送HTTP请求

如何在Node.js中使用Fetch API发送HTTP请求

世界上第一个网站只用了HTML,没有CSS、图片和JavaScript。从那时起,浏览器和网站已经发生了巨大变化。现在,一个网站通常依赖很多不同的资源,比如图片、CSS、字体、JavaScript和JSON等,而动态网站则需要加载更多资源。

作为一种优秀的客户端脚本语言,JavaScript在网站的发展中起到了重要作用。通过XMLHttpRequest(XHR)对象,JavaScript实现了无需刷新页面就能进行客户端与服务器之间的通信。

如今,Fetch API正在挑战这种通信方式。不过,由于Node.js的出现,JavaScript依然很受欢迎,因为它可以用于服务器端编程。

目前,Node.js已经支持Fetch API,但还在实验阶段。本文将介绍什么是Fetch API、如何在Node.js中使用它,以及它为什么优于Axios或XHR等替代方案。


Fetch API是什么

Fetch API是一种用于获取网络资源的应用程序接口,它简化了HTTP请求的操作,比如GET和POST等。它支持Promise新标准,这使得代码更简洁,不需要回调函数。

所有主流浏览器都原生支持Fetch API。JavaScript开发者在服务器端代码中依赖npm的node-fetch包。这个包非常受欢迎,每周有数百万次下载。

Node.js在17.5版本中引入了对Fetch API的实验性支持。从那时起,你可以在编写服务器端JavaScript代码时使用Fetch API,而无需安装第三方库。要使用它,只需运行以下命令:

node --experimental-fetch your_code.js

如何使用Fetch API

在下面的示例中,我将使用一个虚拟网站作为目标。由于Fetch API返回的是一个Promise对象,你可以使用fetch-then语法。要看看Node Fetch的实际效果,可以用代码编辑器创建一个文件,并输入以下代码:

fetch('https://quotes.toscrape.com/random')
    .then((response) => response.text())
    .then((body) => {
        console.log(body);
    });

这段代码发送一个HTTP GET请求并打印HTML内容。

进一步解释,fetch()方法返回一个Promise对象。第一个then()从响应中提取文本,第二个then()打印响应的HTML内容。

将其保存为quotes.js,打开终端并运行以下命令:

node --experimental-fetch quotes.js

它会打印页面的HTML内容。此外,它可能还会打印一条警告,提示Fetch是一个实验性功能。

同样的Node Fetch代码也可以使用async-await语法来编写,如下所示:

(async () => {
    const response = await fetch('https://quotes.toscrape.com/random');
    const body = await response.text();
    console.log(body);
})();

如果你想扩展代码以创建一个网页抓取器,可以安装一个解析器,比如Cheerio,并提取特定的元素。下面的示例提取了一条引用:

const cheerio = require("cheerio");

fetch('https://quotes.toscrape.com/random')
    .then((response) => response.text())
    .then((body) => {
        const $ = cheerio.load(body);
        console.log($('.text').text());

    })

Fetch API中的HTTP头

现在,让我们谈谈响应头。响应对象包含所有的响应头,这些头信息存储在response.headers集合中。如果你想打印响应头,可以按如下方式进行:

const url = 'https://httpbin.org/get'
fetch(url)
    .then(response => {
        for(const pair of response.headers){
            console.log(`${pair[0]}: ${pair[1]}`); 
          }
        return response.text();
    }).then(data => {
        console.log(data);
    });

在使用Node.js运行这段代码时,你会如预期看到所有的响应头。然而,在浏览器中运行时,情况会有所不同。如果你尝试查询的服务器启用了CORS头信息,出于安全原因,浏览器会限制你能访问的头信息。

你只能访问以下头信息:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified和Pragma。更多详情请点击这里。

你还可以使用fetch()的第二个参数发送自定义请求头,在这个参数中可以设置各种选项,包括头信息。下面的例子展示了如何在HTTP请求中发送自定义的User-Agent:

const url = 'https://httpbin.org/get';
fetch(url, {
    headers: {
        "User-Agent": "My User Agent",
    },
})
    .then((response) => response.json())
    .then(data => {
        console.log(data);
    })

如下一节所述,第二个参数可以用于实现更多功能。


发送POST请求

Fetch API默认使用的请求方法是GET。不过,你也可以按如下方式发送POST请求:

fetch(url, {method: “POST”})

让我们练习向一个测试网站发送一些虚拟数据。你需要将要在HTTP POST请求中发送的数据转换成字符串:

const url = 'https://httpbin.org/post'
const data = {
    x: 1920,
    y: 1080,
};
const customHeaders = {
    "Content-Type": "application/json",
}

fetch(url, {
    method: "POST",
    headers: customHeaders,
    body: JSON.stringify(data),
})
    .then((response) => response.json())
    .then((data) => {
        console.log(data);
    });

注意如何设置方法为“POST”,以及如何使用JSON.stringify(data)将数据转换为字符串。

同样,你也可以使用其他HTTP方法,如DELETE、PUT等。


异常处理

由于Node Fetch API返回一个Promise对象,你可以使用fetch – then – catch的方式来处理错误:

fetch('https://invalid_url')
    .then((response) => response.text())
    .then((body) => {
        console.log(body);
    }).catch((error) => {
        console.error('error in execution', error);
    });

如果你使用async-await语法,则可以使用try – catch块处理错误,如下所示:

(async () => {
    try {
        const response = await fetch('https://invalid_url');
        const body = await response.text();
        console.log(body);
    } catch (error) {
        console.error(error);
    }
})();

Axios 与 Fetch API 的对比

Axios是一个流行的 Node 包,可轻松发出 HTTP GET 和 POST 请求。要发送 GET 请求,请调用get()方法,如下所示:

const response = await axios.get(url);

类似地,要发送 POST 请求,请调用post()方法,如下所示:

const response = await axios.post(url);

让我们举个例子来看一下 Node Fetch API 与 Axios 的区别。

向 https://httpbin.org/post 发送一个 POST 请求,并传入 JSON 数据。这里需要注意的要点如下:

  • JSON 数据。
  • 自定义请求标头。
  • 响应将采用 JSON 格式

使用 Axios 和 Fetch API 编写相同的代码将会区分出差异。

以下代码使用了 Axios:

const axios = require('axios');
const url = 'https://httpbin.org/post'
const data = {
    x: 1920,
    y: 1080,
};
const customHeaders = {
    "Content-Type": "application/json",
}
axios.post(url, data, {
    headers: customHeaders,
})
.then(({ data }) => {
    console.log(data);
})
.catch((error) => {
    console.error(error);
});

下面的代码使用了 Fetch API:

const url = 'https://httpbin.org/post'
const data = {
    x: 1920,
    y: 1080,
};
const customHeaders = {
    "Content-Type": "application/json",
}

fetch(url, {
    method: "POST",
    headers: customHeaders,
    body: JSON.stringify(data),
})
    .then((response) => response.json())
    .then((data) => {
        console.log(data);
    })
    .catch((error) => {
        console.error(error);
    });

这两个代码片段都会产生相同的输出。

从上面的例子可以看出,Axios 和 Fetch API 之间有以下区别:

  • Fetch API 使用请求的body属性,而 Axios 使用data属性。
  • 使用Axios,可以直接发送JSON数据,而Fetch API需要转换为字符串。
  • Axios 可以直接处理 JSON。Fetch API 需要先调用response.json()方法才能获取 JSON 格式的响应。
  • 对于 Axios,响应数据变量名必须是 data;对于 Fetch API,响应数据变量名可以是任何内容。
  • Axios 允许使用进度事件轻松监控更新进度。Fetch API 中没有直接方法。
  • Fetch API 不支持拦截器,而 Axios 则支持。
  • Fetch API 允许流式传输响应,而 Axios 则不允许。

结    论

把Fetch API添加到Node.js中是大家期待已久的功能。截至本文撰写时,这个功能还在实验阶段。你可以在生产环境中使用node-fetch包,代码基本一样。结合Cheerio等库,Fetch API也可以用于网页抓取。

Written by 河小马

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