深入解析Node.js中5種發起HTTP請求的方法
翻譯:瘋狂的技術宅 英文標題:5 Ways to Make HTTP Requests in Node.js 原文連結:www.twilio.com/blog/2017/0…
建立HTTP請求使現代程式語言的核心功能之一,也是很多程式設計師在接觸到新的開發環境時最先遇到的技術之一。在Node.js中有相當多的解決方案,其中有語言內建功能,也有開源社群貢獻的開發庫。下面我們們來看一下比較流行的幾種方式。
在本文的案例中,我們將使用NASA提供的“每日太空照片API”作為互動用的JSON API, 因為太空是有史以來最酷的東西。
在開始之前,請先在自己的計算機上安裝最新版的node.js和npm。
HTTP - 標準庫
首先是標準庫中預設的HTTP
模組。這個模組無需安裝依賴外部即可使用,做到了真正的即插即用。缺點是與其他解決方案相比,用起來不是那麼友好。
下面的程式碼將向NASA的API傳送一個GET
請求,並輸出當天的天文照片的URL,以及它的註解:
const https = require('https');
https.get('https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY', (resp) => {
let data = '';
// A chunk of data has been recieved.
resp.on('data', (chunk) => {
data += chunk;
});
// The whole response has been received. Print out the result.
resp.on('end', () => {
console.log(JSON.parse(data).explanation);
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
複製程式碼
HTTP
和HTTPS
模組提供的大多數功能是相當有限的。你需要以區塊為單位接收響應資料,而不是隻提供一個回撥函式,以便在收到所有資料後就立即執行。如果它是JSON格式你還需要進行手動解析。儘管工作量不大,但是它仍然會帶來一些不必要的操作。
另一個麻煩是,HTTP
和HTTPS
協議分屬兩個模組,因此如果我們使用的API是通過HTTPS
協議進行通訊,則需要HTTPS
模組。
如果你不想向程式碼庫中新增太多的依賴項或希望使用其底層的功能, 那麼可能需要花費更多的精力來獲取所需的資料, 儘管如此,但是它仍然是一個很好的工具。
Request
Request是一個簡化的http客戶端,它和Python的request庫很像。這個庫比預設的http
模組更好用,多年來被開源社群作為開發首選。
自從我開始使用Node.js就一直在用,他對快速完成開發任務很有幫助。與http
模組不同的是,你必須使用npm來安裝它。
在終端下進入到你想要程式碼被下載的目錄中,執行以下命令:
npm install request@2.81.0
複製程式碼
可以看到,不需要寫太多程式碼就能完成前面的功能:
const request = require('request');
request('https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY', { json: true }, (err, res, body) => {
if (err) { return console.log(err); }
console.log(body.url);
console.log(body.explanation);
});
複製程式碼
如果你想要一個使用正常方式處理HTTP請求的苦,那麼Request是一個很好的選擇。如果你想使用Promises,也可以簽出request-promise庫。
Axios
Axios是一個基於promise的HTTP客戶端,可以用於瀏覽器和Node.js。在處理需要更復雜的事件鏈的程式碼時,使用Promises具有很大的優勢。 編寫非同步程式碼可能會令人困惑,而Promises是這個問題的幾種解決方案之一。 它們甚至被用在其它語言中,比如Swift。
使用npm安裝Axios,在終端中輸入以下命令:
npm install axios@0.16.2
複製程式碼
下面的程式碼實現相同的功能,得到URL並解釋當天的天文學圖片。
const axios = require('axios');
axios.get('https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY')
.then(response => {
console.log(response.data.url);
console.log(response.data.explanation);
})
.catch(error => {
console.log(error);
});
複製程式碼
預設情況下,Axios可以解析JSON響應,非常方便。你也可以看到錯誤處理是由.catch()
完成的,現在我們都在使用 promises。
你甚至可以通過axios.all
發起多個併發請求,比如說你想一次性得到兩天的天文圖片可以這樣做:
var axios = require('axios');
axios.all([
axios.get('https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY&date=2017-08-03'),
axios.get('https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY&date=2017-08-02')
]).then(axios.spread((response1, response2) => {
console.log(response1.data.url);
console.log(response2.data.url);
})).catch(error => {
console.log(error);
});
複製程式碼
非同步程式碼很容易地變得十分複雜並且不容易處理, 和 it 解決這個問題的方式可能會讓你的生活更容易從長遠來看。Axios很輕鬆的解決了這個問題,從長遠看來可以使你的開發工作變得輕鬆。
SuperAgent
與Axios類似,SuperAgent 是另一個流行的庫,主要用於瀏覽器中的Ajax請求,但也適用於Node.js。使用以下命令安裝SuperAgent :
npm install superagent@3.5.2
複製程式碼
SuperAgent最酷的地方是能進行鏈式呼叫,你可以把其它函式鏈到像query()
這樣的請求上,並且新增引數。在前面的例子中我們都是手動新增它們。請注意 SuperAgent 是怎樣提供這種功能的:
const superagent = require('superagent');
superagent.get('https://api.nasa.gov/planetary/apod')
.query({ api_key: 'DEMO_KEY', date: '2017-08-02' })
.end((err, res) => {
if (err) { return console.log(err); }
console.log(res.body.url);
console.log(res.body.explanation);
});
複製程式碼
和axios一樣,你也不用自己解析去JSON響應,這非常酷。
Got
如果你想用一個更輕量級的庫,Got是另外一個選擇。它也可用於Twilio Functions。
再來一遍,實用npm安裝Got:
npm install got@7.1.0
複製程式碼
和Axios一樣,Got也能同Promises一起很好的工作。下面的程式碼做的事情和前面的例子一樣:
const got = require('got');
got('https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY', { json: true }).then(response => {
console.log(response.body.url);
console.log(response.body.explanation);
}).catch(error => {
console.log(error.response.body);
});
複製程式碼
如果你想要一個不像Request那樣臃腫的輕量級的庫,使用Got就對了。
最後的想法
以上並不是全部的解決方案,不過看到了這裡,你知道了在Node.js中一些流行的HTTP庫中的基本功能是怎樣工作的。還有一些庫,例如node-fetch將瀏覽器的獲取(fetch)功能移植到後端。在其他語言中也有各種類似的庫解決這個問題,比如 Python 和 Ruby 。