Node.js系列 :5個方法產生非同步Http 請求
作為我的第一篇 Post,就從 Node.js 開始吧!
相信各位在寫程式時都避不開一個問題:大量的 Http Request!在存取任何型態的遠端資源 ( API、網頁、File…… )時都會用到。而到底有哪些模組在Node.js 中可以用來達成目標呢 ?我們往下看吧!
以下分享為了簡潔以及易於理解,本文皆使用 GET 請求來說明。
你將學到
- 如何用不同的 modules 發出Http請求
- 每一個 module 的優缺點
閱讀需求
- 建議對 Javascript 和 ES6 語法有基本的了解
- 實際在 Local 安裝 Node.js 7.6.0以上
建置專案
創建一個空的資料夾並且用 npm 初始化它
mkdir test && cd $_ npm init -y
Node.js 中有兩種簡明的模式可以產生 Http 請求:
- 經典的 callback pattern
- (用多了會導致著名的 callback hell,非常難維護!)
- 支援 Promises,代表可以使用 async/await
- (Promises 觀念非常重要,不懂的建議先從下方連結理解喔)
https://developers.google.com/web/fundamentals/primers/promises?hl=zh-tw
我們就從 callback 開始吧!
1. http.get 和 https.get
第一個選擇就是 Node.js 內建原生的 http.get 和 https.get,如果只是要做非常單純的 GET 請求,可以用他們就好。
優點:
- 原生 API ,不用額外安裝 module
- 回應是串流所以需要較多的手工處理
- (優點也是缺點,但我覺得可以多學點也是個優點?)
缺點:
- 會多寫很多 code,之後可能很難維護
- 同第二個優點
- 沒有支援 Promises
範例 http-native.js
:
const https = require("https"); const url = "https://api.jasontechlab.com/posts/1"; https.get(url, res => { res.setEncoding("utf8"); let body = ""; //接收資料 res.on("data", data => { body += data; }); //接收完畢 res.on("end", () => { body = JSON.parse(body); console.log(body); }); });
接下來執行:
node http-native.js
結果:
{ "userId": 1, "id": 1, "title": "delectus aut autem", "completed": false }
http.get 中第一個參數是網址 url ,第二個參數是一個 callback res。
res是一個 http.ClientRequest 物件,這意味著你如果要對 response body 進行操作,則必須聽取一些事件,請看範例中res.on()
的部分,在範例中我只是簡單的 console.log 出 API 回傳的資料,實務上應該會有更複雜的操作或是將資料傳入一個 callback function:
function makeResponseHandler (callback) { return function (response) { //在這處理 data, node.js native wahy callback(null, result); } }; return { apiGet: function(url, callback) { http.get(url, makeResponseHandler(callback)); } }
小結:
callback模式還有一個 request module ,但是在今年二月已經被廢棄了,有興趣的可以去官網看看:
https://www.npmjs.com/package/request
用原生的方法雖然會多寫很多 code,但是你因為被迫於處理原生的 events,
會去多鑽一些 Node.js的底層,我覺得這是好事,推薦初學者使用!
接下來要學的可以用一句話代表:I Promise I’ll be async !
2. node-fetch
node-fetch 是 Fetch API 在 Node.js 中的實作,基本上跟 window.fetch 相同,所以基本上使用起來也是非常直覺。
優點:
- 支援 Promises
- 使用上接近 window.fetch
- 依賴很少
缺點:
- 不支持同步請求
- 只會對網路報錯,對 400, 500 等都當作是成功的請求,需要封裝處理
- 默認不會带 cookie,需要添加額外配置
- 不支持abort,不支持超時控制,使用setTimeout及Promise.reject的實現的超時控制不能阻止請求過程繼續在後台執行,造成了流量浪費
- 沒有辦法原生的監測請求進度
安裝:
npm i node-fetch --save
範例 node-fetch.js
:
const fetch = require("node-fetch"); const url = "https://jsonplaceholder.typicode.com/posts/1"; const getData = async url => { try { const response = await fetch(url); const json = await response.json(); console.log(json); } catch (error) { console.log(error); } }; getData(url);
執行:
node node-fetch.js
小結:
我本身不是很愛用 node-fetch,因為我不愛 Fetch API所以也不愛它XD,想到處理回傳時要寫 json() 和兩次 then() 就覺得很煩,不過每人都有所愛,選擇自己適合的最重要。
3. r2
request module 的作者在2017年開發的,也算是 Fetch API的另一個實作,這意味者:r2 底層是 node-fetch……
優缺點同 node-fetch
安裝:
npm i r2
範例 r2.js
:
const r2 = require("r2"); const url = "https://jsonplaceholder.typicode.com/posts/1"; const getData = async url => { try { const response = await r2(url).json; console.log(response); } catch (error) { console.log(error); } }; getData(url);
執行:
node r2.js
小結:
我承認我沒有花時間去研究它(因為本來就對 node-fetch有排斥了),但有興趣的可以去看看它新增的特性以及改良的地方,搞不好你會喜歡。
4. axios
axios 是現在超流行的 module,也是我最常使用的。它天生就支援了 Promises所以 code 寫起來非常簡潔。
axios 被拿來使用在前後端都可以,而且可以針對 response 自動轉換,不需要像 node-fetch 一樣寫 json() 啦!
優點:
- 支援Promises
- 使用容易簡明
- 只有兩個依賴
缺點:
- ?? (有知道的可以跟我說)
安裝:
npm i axios
範例 axios-module.js
:
const axios = require("axios"); const url = "https://jsonplaceholder.typicode.com/posts/1"; const getData = async url => { try { const response = await axios.get(url); const data = response.data; console.log(data); } catch (error) { console.log(error); } }; getData(url);
執行:
node axios-module.js
小結:
目前我找不太到 axios 缺點,他是如此的易用跟方便配置,或許等以後 Fetch 技術成熟到可以取代 Ajax 時的那一天才有可能找到吧。
總結:
通過以上簡易的比較,大家都可以試試,目前還是最推薦使用 axios。我最近有關注一個後起之秀 bent,它用起來比 axios 更為簡潔,大家有興趣可以去嘗試一下:
https://github.com/mikeal/bent