JavaScript >> Javascript 文檔 >  >> Node.js

使用 node-fetch 在 Node.js 中發出 HTTP 請求

簡介

Web 應用程序通常需要與 Web 服務器通信以獲取各種資源。您可能需要從外部網絡服務器或 API 獲取數據或將數據發佈到外部網絡服務器或 API。

使用客戶端 JavaScript,這可以使用 fetch API 和 window.fetch() 來實現 功能。在 NodeJS 中,多個包/庫可以實現相同的結果。其中之一是 node-fetch 包。

node-fetch 是一個輕量級模塊,使我們能夠使用 fetch() NodeJS 中的函數,功能與 window.fetch() 非常相似 在原生 JavaScript 中,但有一些不同。

開始使用node-fetch

使用 node-fetch 在您的項目中,cd 進入你的項目目錄,然後運行:

$ npm install node-fetch

從 3.0 版開始,node-fetch 是一個 ESM-only 模塊 - 你不能用 require() 導入它 .如果您自己不使用 ESM,建議您使用 2.0 版本而不是最新版本,在這種情況下您可以使用標準的 require() 語法。

要在代碼中使用模塊(對於 3.0 之前的版本),請使用:

const fetch = require('node-fetch');

如果您使用 ESM,您將以不同的方式導入模塊:

import fetch from 'node-fetch';

注意: node-fetch之間的API 3.0和2.0是一樣的,只是導入不同。

要安裝特定版本的模塊,可以使用 npm

$ npm install [email protected]

如前所述,fetch() node-fetch 中的函數 模塊的行為與原生 window.fetch() 非常相似 功能。它的簽名是:

fetch(url[, options]);

url 參數只是我們希望獲取的資源的直接 URL。它必須是絕對 URL,否則該函數將引發錯誤。可選的 options 當我們要使用 fetch() 時使用參數 除了簡單的 GET 請求,但我們稍後會更深入地討論。

該函數返回一個 Response 包含有關 HTTP 響應的有用功能和信息的對象,例如:

  • text() - 以字符串形式返迴響應正文
  • json() - 將響應體解析為 JSON 對象,如果無法解析則拋出錯誤
  • statusstatusText - 包含有關 HTTP 狀態代碼的信息
  • ok - 等於 true 如果 status 是一個 2xx 狀態碼(一個成功的請求)
  • headers - 包含響應頭的對象,可以使用 get() 訪問特定的頭 功能。

使用 node-fetch 發送 GET 請求

從 Web 服務器獲取數據有兩種常見用例。您可能希望從 Web 服務器、整個網頁或使用 REST API 的數據中檢索文本。 node-fetch 包允許你做所有這些。

為您的項目創建一個目錄,cd 進入目錄並使用默認設置初始化一個Node項目:

$ npm init -y

這將創建一個 package.json 目錄中的文件。接下來,安裝 node-fetch 如上圖並添加一個 index.js 文件。

獲取文本或網頁

讓我們做一個簡單的 GET 對谷歌主頁的請求:

fetch('https://google.com')
    .then(res => res.text())
    .then(text => console.log(text));

在上面的代碼中,我們正在加載 node-fetch 模塊,然後獲取谷歌主頁。我們添加到 fetch() 的唯一參數 function 是我們向其發出 HTTP 請求的服務器的 URL。因為 node-fetch 是基於承諾的,我們鏈接了幾個 .then() 幫助我們管理請求的響應和數據的功能。

在這一行中,我們正在等待接收來自 Google 網絡服務器的響應並將其轉換為文本格式:

.then(res => res.text());

在這裡,我們等待上一次轉換的結果,並將其打印到控制台:

.then(text => console.log(text));

如果我們從控制台運行上面的代碼:

$ node index.js

免費電子書:Git Essentials

查看我們的 Git 學習實踐指南,其中包含最佳實踐、行業認可的標準以及隨附的備忘單。停止谷歌搜索 Git 命令並真正學習 它!

我們將把谷歌主頁的整個 HTML 標記記錄到控制台:

<!doctype html>
<html itemscope="" itemtype="http://schema.org/WebPage" lang="en-RS">
    <head>
        <meta charset="UTF-8">
        <meta content="origin" name="referrer">
        <!-- Rest of the page -->

從 REST API 獲取 JSON 數據

node-fetch 的另一個常見用例 模塊正在使用 REST API 獲取數據。

我們將從 JSONPlaceholder REST API 檢索虛假用戶數據。和以前一樣,fetch() 函數接受服務器的 URL 並等待響應。

讓我們看看它是如何工作的:

fetch('https://jsonplaceholder.typicode.com/users')
    .then(res => res.json())
    .then(json => {
        console.log("First user in the array:");
        console.log(json[0]);
        console.log("Name of the first user in the array:");
        console.log(json[0].name);
})

HTTP 響應的主體包含 JSON 格式的數據,即包含用戶信息的數組。考慮到這一點,我們使用了 .json() 函數,這使我們能夠輕鬆訪問各個元素及其字段。

運行這個程序會給我們:

First element in the array:
{
  id: 1,
  name: 'Leanne Graham',
  username: 'Bret',
  email: '[email protected]',
  address: {
    street: 'Kulas Light',
    suite: 'Apt. 556',
    city: 'Gwenborough',
    zipcode: '92998-3874',
    geo: { lat: '-37.3159', lng: '81.1496' }
  },
  phone: '1-770-736-8031 x56442',
  website: 'hildegard.org',
  company: {
    name: 'Romaguera-Crona',
    catchPhrase: 'Multi-layered client-server neural-net',
    bs: 'harness real-time e-markets'
  }
}

Name of the first person in the array:
Leanne Graham

我們也可以打印出 res.json() 返回的整個 JSON .

使用 node-fetch 發送 POST 請求

我們也可以使用 fetch() 發布數據而不是檢索數據的功能。正如我們前面提到的,fetch() 函數允許添加一個額外的參數來製作 POST 對 Web 服務器的請求。如果沒有這個可選參數,我們的請求是 GET 請求,默認情況下。

我們可以使用此參數設置許多可能的選項,但我們將在本文中使用的唯一選項是 method , bodyheaders .

這些字段的含義很簡單:method 設置我們使用的 HTTP 請求類型(POST 在我們的例子中),body 包含我們請求的主體/數據,以及 headers 包含所有必要的標頭,在我們的例子中就是 Content-Type 所以在解析我們的請求時不會有任何混淆。

有關選項的完整列表,您可以訪問文檔。

我們將通過向 JSONPlaceholder 的待辦事項添加新項目來演示其工作原理。讓我們為 id 的用戶在該列表中添加一個新項目 等於 123 .首先,我們需要創建一個todo 對象,然後在將其添加到 body 時將其轉換為 JSON 字段:

let todo = {
    userId: 123,
    title: "loren impsum doloris",
    completed: false
};

fetch('https://jsonplaceholder.typicode.com/todos', {
    method: 'POST',
    body: JSON.stringify(todo),
    headers: { 'Content-Type': 'application/json' }
}).then(res => res.json())
  .then(json => console.log(json));

該過程與製作 GET 非常相似 要求。我們稱之為 fetch() 函數,帶有適當的 URL,我們使用 fetch() 的可選參數設置必要的選項 功能。我們使用 JSON.stringify() 在將對象發送到 Web 服務器之前將其轉換為 JSON 格式的字符串。然後,與檢索數據一樣 - 我們等待響應,將其轉換為 JSON,然後將其打印到控制台。

運行代碼會給我們輸出:

{
  userId: 123,
  title: 'loren impsum doloris',
  completed: false,
  id: 201
}

處理異常和錯誤

由於各種原因,我們的請求有時會失敗 - fetch() 中出現錯誤 功能、互聯網問題、內部服務器錯誤等。我們需要一種方法來處理這些情況,或者至少能夠看到它們的發生。

我們可以通過添加 catch() 來處理運行時異常 在承諾鏈的末端。讓我們添加一個簡單的 catch() 函數到我們上面的程序中:

let todo = {
    userId: 123,
    title: "loren impsum doloris",
    completed: false
}

fetch('https://jsonplaceholder.typicode.com/todos', {
    method: 'POST',
    body: JSON.stringify(todo),
    headers: { 'Content-Type': 'application/json' }
}).then(res => res.json())
  .then(json => console.log(json))
  .catch(err => console.log(err));

理想情況下,您不應該簡單地忽略和打印錯誤,而應該有一個系統來處理它們。

我們應該記住,如果我們的響應有 3xx/4xx/5xx 狀態碼,那麼請求要么失敗,要么客戶端需要採取額外的步驟。

即,3xx HTTP 狀態碼表示客戶端需要採取額外的步驟,4xx 碼表示無效請求,5xx 碼表示服務器錯誤。所有這些狀態碼都告訴我們,我們的請求實際上並不成功。

catch() 不會註冊任何這些情況,因為與服務器的通信很順利,即我們發出請求並成功獲得響應。這意味著我們需要採取額外的步驟來確保我們涵蓋了客戶端-服務器通信成功但我們沒有收到任何成功的 (2xx) HTTP 狀態代碼的情況。

確保失敗的請求引發錯誤的一種常見方法是創建一個函數來檢查來自服務器的響應的 HTTP 狀態。在那個函數中,如果狀態碼不表示成功,我們可以拋出一個錯誤和 catch() 會抓到的。

我們可以使用前面提到的ok Response 的字段 對象,等於 true 如果狀態碼是2xx。

讓我們看看它是如何工作的:

function checkResponseStatus(res) {
    if(res.ok){
        return res
    } else {
        throw new Error(`The HTTP status of the reponse: ${res.status} (${res.statusText})`);
    }
}

fetch('https://jsonplaceholder.typicode.com/MissingResource')
    .then(checkResponseStatus);
    .then(res => res.json());
    .then(json => console.log(json));
    .catch(err => console.log(err));

我們在 Promise 鏈的開頭(在解析響應正文之前)使用了該函數,以查看我們是否遇到了問題。您也可以改為拋出自定義錯誤。

同樣,您應該制定處理此類錯誤的策略,而不僅僅是打印到控制台。

如果一切按預期進行,並且狀態碼指示成功,則程序將照常進行。

結論

向 Web 服務器發出請求是一項常見的 Web 開發任務,在本文中,我們了解瞭如何使用 node-fetch 有效地完成它 - 一個使原生瀏覽器獲取 API 與 NodeJS 兼容的庫。

除此之外,我們還研究瞭如何處理 HTTP 請求可能發生的錯誤。


Tutorial JavaScript 教程
  1. React 開發人員的反應式編程第 2 部分 - 與 React 集成

  2. 我的 React 應用程序中檢測到無法訪問的代碼錯誤 - 如何修復?

  3. JavaScript Clean Code — 函數和約定啟發式

  4. D3v6 獲取g元素位置

  5. 10 個必須知道的 CSS 和 CSS3 資源和工具

  6. 堅硬的。 JavaScript 中圍繞你的原則

  7. 訪問 javascript 函數(生成器)中的變量

  1. 承諾返回數據”

  2. Javascript 承諾 101

  3. WebAssembly 和 Web 前端開發的演變

  4. Javascript:以編程方式將非彈出式 SELECT 元素滾動到 Chrome 的底部

  5. 將靜態分析工具與開源一起使用!

  6. 使用 Next.js 和 Express.js 的服務器渲染 React Next Starter

  7. .NET 6 中的 GraphQL 入門 - 第 3 部分(使用 ApolloClient React)

  1. 可以polygon.setPath();用於完全重新定義多邊形?

  2. React 的核心概念

  3. SitePoint CSS 參考內測

  4. 末日的無障礙地牢