原文來源:https://blog.logrocket.com/5-ways-make-http-requests-node-js/
原文作者:Geshan Manandhar
譯者:一川
在 Node.js 中發出 HTTP 請求的方法有多種。可以通過使用 Node.js 提供的標準內置 HTTP/HTTPS 模塊、利用 Node 環境中包含的 Fetch API 或選擇第三方 npm 包來簡化流程來實現此目的。
在本文中,將探索本機 HTTPS 模塊和 Fetch API,并研究流行的 npm 包,例如 Axios、Got、superagent 和 node-fetch,以促進高效地發出 HTTP 請求。
將使用每個 HTTP 客戶端向 JSONPlaceholder API 發出 GET 請求。它將向我們發送 10 個用戶的數據。將在控制臺上記錄每個用戶名和 ID。
Let’s get started!
Node.js 帶有內置的 HTTP 和 HTTPS 模塊。在下面的示例中,使用 HTTPS 模塊對占位符 API 執行 GET 請求:
const https = require('https');https.get('https://jsonplaceholder.typicode.com/users', res => { let data = []; const headerDate = res.headers && res.headers.date ? res.headers.date : 'no response date'; console.log('Status Code:', res.statusCode); console.log('Date in Response header:', headerDate); res.on('data', chunk => { data.push(chunk); }); res.on('end', () => { console.log('Response ended: '); const users = JSON.parse(Buffer.concat(data).toString()); for(user of users) { console.log(`Got user with id: ${user.id}, name: ${user.name}`); } });}).on('error', err => { console.log('Error: ', err.message);});
讓我們看一下代碼,需要使用nodejs內置的 https 模塊,該模塊在任何標準 Node.js 安裝中都可用。無需 package.json 文件或 npm install 即可開始使用它。
接下來,將 data 初始化為空數組,并記錄響應標頭中的狀態代碼和日期。每當獲得一塊數據時,就把它推入 data 數組中。收到所有響應后,連接數據數組,將其轉換為字符串,并解析 JSON 以獲取用戶列表。循環訪問用戶并將用戶 ID 和名稱記錄到控制臺。
這里需要注意一件事:如果請求出現錯誤,錯誤消息將記錄在控制臺上。上述代碼可作為拉取請求使用。
您可以使用 node native-https.js 命令執行上面的代碼,前提是您將文件命名為 native-https.js 。它應該顯示如下輸出:
圖片
可以使用相同的方法來運行本文中的所有其他示例;他們將顯示類似的輸出。打印狀態代碼、響應標頭中的日期以及響應正文中的用戶 ID 和名稱。
Node.js 在 v16.15.0 中提供了 Fetch API 的瀏覽器兼容實現的實驗版本,并在 Node v21 中變得穩定。
Fetch 在環境中本身可用,無需導入或單獨需要。這個內置 API 具有多種優勢:無需持續維護,最大限度地減少安全問題,并且不會影響捆綁包大小或通常與第三方軟件包相關的許可問題。
您可以將 Fetch API 與 async/await 或 Promise 鏈結合使用:
(async () => { try { const res = await fetch('https://jsonplaceholder.typicode.com/users'); const headerDate = res.headers && res.headers.get('date') ? res.headers.get('date') : 'no response date'; console.log('Status Code:', res.status); console.log('Date in Response header:', headerDate); const users = await res.json(); for(user of users) { console.log(`Got user with id: ${user.id}, name: ${user.name}`); } } catch (err) { console.log(err.message); //can be console.error }})();
由于 Fetch API 與瀏覽器兼容,因此您為使用 Fetch API 在瀏覽器中獲取數據而編寫的代碼也可以在 Node.js 中使用而無需修改,反之亦然。
Axios 是一個非常流行的基于 Promise 的請求庫。它是一個適用于瀏覽器和 Node.js 的 HTTP 客戶端。它還包括一些方便的功能,例如攔截請求和響應數據,以及自動將請求和響應數據轉換為 JSON。
const axios = require('axios');axios.get('https://jsonplaceholder.typicode.com/users') .then(res => { const headerDate = res.headers && res.headers.date ? res.headers.date : 'no response date'; console.log('Status Code:', res.status); console.log('Date in Response header:', headerDate); const users = res.data; for(user of users) { console.log(`Got user with id: ${user.id}, name: ${user.name}`); } }) .catch(err => { console.log('Error: ', err.message); });
上面的示例中的代碼比前一個示例中的代碼少,因為它使用了 Promise 鏈。但是,您可以將其變成 async/await。
解釋一下上面的例子做了什么。需要使用 axios 庫,然后使用 axios.get 方法向 JSONPlaceholder API 發出 GET 請求。使用承諾鏈來處理響應。在 then 方法回調中,將狀態代碼和日期記錄到控制臺。
Axios 將響應數據轉換為開箱即用的 JSON。上例中的響應數據是用戶數組。循環遍歷它并將用戶 ID 和名稱記錄到控制臺。
Got 是 Node.js 的另一個流行的 HTTP 請求庫。 Got 具有基于承諾的 API,其 HTTP/2 支持和分頁 API 是其獨特的特點。
const got = require('got');got.get('https://jsonplaceholder.typicode.com/users', {responseType: 'json'}) .then(res => { const headerDate = res.headers && res.headers.date ? res.headers.date : 'no response date'; console.log('Status Code:', res.statusCode); console.log('Date in Response header:', headerDate); const users = res.body; for(user of users) { console.log(`Got user with id: ${user.id}, name: ${user.name}`); } }) .catch(err => { console.log('Error: ', err.message); });
上面的代碼示例與 Axios 類似,但有兩個主要區別:
其他的與之前對 axios 的要求保持一致。您可以在此拉取請求中看到上面的示例。
superagent 于 2011 年 4 月由 VisionMedia 首次發布,是最古老的 Node.js 請求包之一。 superagent 將自己定位為“小型、漸進式客戶端 HTTP 請求庫和 Node.js 模塊,具有相同的 API,支持許多高級 HTTP 客戶端功能。”它提供基于回調和基于承諾的 API。 superagent 有幾個插件,您可以使用它來擴展其功能。
const superagent = require('superagent');(async () => { try { const res = await superagent.get('https://jsonplaceholder.typicode.com/users'); const headerDate = res.headers && res.headers.date ? res.headers.date : 'no response date'; console.log('Status Code:', res.statusCode); console.log('Date in Response header:', headerDate); const users = res.body; for(user of users) { console.log(`Got user with id: ${user.id}, name: ${user.name}`); } } catch (err) { console.log(err.message); //can be console.error }})();
Superagent 已經成熟且經過實戰考驗,因此非常可靠。我們還可以使用 SuperTest 庫測試超級代理調用。與前面的示例一樣,上面的超級代理示例可作為拉取請求使用。
node-fetch 是 Node.js 的另一個非常流行的 HTTP 請求庫 - 根據 npm 趨勢,在 2024 年 2 月的第一周,它的下載量超過 5000 萬次。
用他們自己的話來說,“node-fetch 是一個輕量級模塊,它將 Fetch API ( window.fetch ) 引入 Node.js。”其功能包括與基于瀏覽器的 window.fetch 以及本機 Promise 和異步函數的一致性。
const fetch = require('node-fetch');(async () => { try { const res = await fetch('https://jsonplaceholder.typicode.com/users'); const headerDate = res.headers && res.headers.get('date') ? res.headers.get('date') : 'no response date'; console.log('Status Code:', res.status); console.log('Date in Response header:', headerDate); const users = await res.json(); for(user of users) { console.log(`Got user with id: ${user.id}, name: ${user.name}`); } } catch (err) { console.log(err.message); //can be console.error }})();
讓我們回顧一下與使用 superagent 和 async/await 的示例相比的一些差異:
除了內置的 HTTP/HTTPS 模塊和內置的 fetch API 之外,所有其他四個 HTTP 客戶端庫都可以作為 npm 包提供。以下是根據 npm 趨勢顯示的過去六個月每周下載統計數據的快速概覽:
從每月下載量來看,過去六個月中,node-fetch 最受歡迎,而 superagent 則最不受歡迎。為了更全面地了解它們的受歡迎程度,讓我們檢查其他指標,從 Got GitHub 存儲庫上提供的比較表中獲取見解:
從上表來看,node-fetch 是下載次數最多的軟件包,最大安裝大小為 7.45MB。 Axios 擁有最多的 GitHub 星數,達到 10.3 萬——比其他所有三個庫的總和還多。
const express = require("express");const app = express();const PORT = process.env.PORT || 3000;app.get("/", (req, res) => { res.send("Hello world!");});app.listen(PORT, () => { console.log(`Your app is listening on port ${PORT}`);});
這就是使用 Express.js 實現基本 HTTP 服務的方式。
在本節中,我們將探討如何在 Node.js 服務器中處理 POST 請求。當用戶提交 HTML 表單或發出 AJAX POST 請求時,會發生典型的 POST 請求。
當 POST 請求到達其預期端點時,您將訪問 POST 數據,在回調函數中解析它,驗證和清理數據,并可能發回響應。但是,您應該意識到,在使用普通 Node.js 服務器時,解析 HTTP 請求正文可能會很乏味。
下面的代碼是普通 Node.js HTTP 服務器的基本實現。它有一個基本的 HTML 表單,您可以使用它來發出 POST 請求。請求正文的結構取決于編碼類型。這些編碼類型包括 application/x-www-form-urlencoded 、 multipart/form-data 和 text/plain :
const http = require("http");const html = `<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" cnotallow="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <form actinotallow="/submit-form" enctype="application/x-www-form-urlencoded" method="POST"> <label> Enter Name: <input type="text" autocomplete="name" name="name" required /> </label> <input type="submit" /> </form> </body></html>`;const server = http.createServer((req, res) => { switch (req.method) { case "GET": if (req.url === "/") { res.writeHead(200, { "Content-Type": "text/html" }); res.end(html); } else { res.writeHead(404, { "Content-Type": "text/plain" }); res.end("Page not found"); } break; case "POST": if (req.url === "/submit-form") { let body = ""; req.on("data", (data) => { body += data; }); req.on("end", () => { console.log("Request body: " + body); // Parse, validate, and sanitize res.writeHead(200, { "Content-Type": "application/json" }); res.end(JSON.stringify({ body })); }); } else { res.writeHead(404, { "Content-Type": "text/plain" }); res.end("Page not found"); } break; default: res.writeHead(405, { "Content-Type": "text/plain" }); res.end("Method not supported"); }});const PORT = process.env.PORT || 3000;server.listen(PORT, () => { console.log(`Your app is listening on PORT ${PORT}`);});
解析 POST 請求正文后,您需要驗證和清理數據。然后,您可以將數據保存在數據庫中、對用戶進行身份驗證或重定向到適當的頁面。
大多數后端框架都具有用于解析 HTTP 請求正文的內置功能。使用 Express.js,當請求正文具有 application/x-www-form-urlencoded 編碼時,您可以使用內置的 express.urlencoded() 中間件。中間件將使用請求數據的鍵值對填充 req.body :
const express = require("express");const path = require("path");const app = express();const PORT = process.env.PORT || 3000;app.use(express.static("public"));app.use(express.json());app.use(express.urlencoded({ extended: true }));app.post("/submit-form", (req, res) => { console.log(req.body); res.json(req.body);});app.get("/", (req, res) => { res.sendFile(path.join(__dirname, "index.html"));});app.listen(PORT, () => { console.log(`Your app is listening on port ${PORT}`);});
對于 multipart/form-data 編碼,需要使用第三方包,例如busboy、Multer或formidable。
下面的代碼說明了如何使用 Multer。由于它不是內置中間件,因此請務必首先從 npm 包注冊表安裝它:
const express = require("express");const path = require("path");const multer = require("multer");const app = express();const upload = multer();const PORT = process.env.PORT || 3000;app.use(express.static("public"));app.post("/submit-form", upload.none(), (req, res) => { console.log("req.body: ", req.body); console.log("Content-Type: ", req.get("Content-Type")); res.json(req.body);});app.get("/", (req, res) => { res.sendFile(path.join(__dirname, "index.html"));});app.listen(PORT, () => { console.log(`Your app is listening on port ${PORT}`);});
最后,Express還有一個內置的中間件,用于解析具有 text/plain 編碼的請求體。它的用法與我們之前看過的中間件類似。你可以像這樣安裝它:
app.use(express.text());
axios比superagent的功能列表很長,盡管 node-fetch 看起來很有前途并且安裝大小很小,但我不確定該 API 是否足夠用戶友好——至少對我來說是這樣。
您可能會注意到我的討論中省略了 Request npm 包。盡管 Request 持續受歡迎,每周下載量達到 1142 萬次,但截至 2024 年 2 月已被棄用,這使其成為一個不切實際的選擇。
所有這些庫主要做同樣的事情——就像你喜歡哪個品牌的咖啡一樣,最終你仍然在喝咖啡。根據您的用例明智地選擇,并做出正確的權衡以獲得最大利益。
本文鏈接:http://www.www897cc.com/showinfo-26-76491-0.html在 Node.js 中發出 HTTP 請求的五種方法
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com
上一篇: JS問題:簡單的Console.log不要再用了!試試這個
下一篇: 我應該使用按鈕還是鏈接