深入解析Node.js中5種發(fā)起HTTP請(qǐng)求的方法
創(chuàng)建HTTP請(qǐng)求使現(xiàn)代編程語(yǔ)言的核心功能之一,也是很多程序員在接觸到新的開(kāi)發(fā)環(huán)境時(shí)***遇到的技術(shù)之一。在Node.js中有相當(dāng)多的解決方案,其中有語(yǔ)言內(nèi)置功能,也有開(kāi)源社區(qū)貢獻(xiàn)的開(kāi)發(fā)庫(kù)。下面咱們來(lái)看一下比較流行的幾種方式。
在本文的案例中,我們將使用NASA提供的“每日太空照片API”作為交互用的JSON API,
因?yàn)樘帐怯惺芬詠?lái)最酷的東西。
在開(kāi)始之前,請(qǐng)先在自己的計(jì)算機(jī)上安裝***版的node.js和npm。
HTTP - 標(biāo)準(zhǔn)庫(kù)
首先是標(biāo)準(zhǔn)庫(kù)中默認(rèn)的HTTP模塊。這個(gè)模塊無(wú)需安裝依賴外部即可使用,做到了真正的即插即用。缺點(diǎn)是與其他解決方案相比,用起來(lái)不是那么友好。
下面的代碼將向NASA的API發(fā)送一個(gè)GET請(qǐng)求,并輸出當(dāng)天的天文照片的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模塊提供的大多數(shù)功能是相當(dāng)有限的。你需要以區(qū)塊為單位接收響應(yīng)數(shù)據(jù),而不是只提供一個(gè)回調(diào)函數(shù),以便在收到所有數(shù)據(jù)后就立即執(zhí)行。如果它是JSON格式你還需要進(jìn)行手動(dòng)解析。盡管工作量不大,但是它仍然會(huì)帶來(lái)一些不必要的操作。
另一個(gè)麻煩是,HTTP和HTTPS協(xié)議分屬兩個(gè)模塊,因此如果我們使用的API是通過(guò)HTTPS協(xié)議進(jìn)行通信,則需要HTTPS模塊。
如果你不想向代碼庫(kù)中添加太多的依賴項(xiàng)或希望使用其底層的功能, 那么可能需要花費(fèi)更多的精力來(lái)獲取所需的數(shù)據(jù), 盡管如此,但是它仍然是一個(gè)很好的工具。
Request
Request是一個(gè)簡(jiǎn)化的http客戶端,它和Python的request庫(kù)很像。這個(gè)庫(kù)比默認(rèn)的http 模塊更好用,多年來(lái)被開(kāi)源社區(qū)作為開(kāi)發(fā)***。
自從我開(kāi)始使用Node.js就一直在用,他對(duì)快速完成開(kāi)發(fā)任務(wù)很有幫助。與http 模塊不同的是,你必須使用npm來(lái)安裝它。
在終端下進(jìn)入到你想要代碼被下載的目錄中,運(yùn)行以下命令:
- npm install request@2.81.0
可以看到,不需要寫(xiě)太多代碼就能完成前面的功能:
- 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);
- });
如果你想要一個(gè)使用正常方式處理HTTP請(qǐng)求的苦,那么Request是一個(gè)很好的選擇。如果你想使用Promises,也可以簽出request-promise庫(kù)。
Axios
Axios是一個(gè)基于promise的HTTP客戶端,可以用于瀏覽器和Node.js。在處理需要更復(fù)雜的事件鏈的代碼時(shí),使用Promises具有很大的優(yōu)勢(shì)。 編寫(xiě)異步代碼可能會(huì)令人困惑,而Promises是這個(gè)問(wèn)題的幾種解決方案之一。 它們甚至被用在其它語(yǔ)言中,比如Swift。
使用npm安裝Axios,在終端中輸入以下命令:
- npm install axios@0.16.2
下面的代碼實(shí)現(xiàn)相同的功能,得到URL并解釋當(dāng)天的天文學(xué)圖片。
- 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);
- });
默認(rèn)情況下,Axios可以解析JSON響應(yīng),非常方便。你也可以看到錯(cuò)誤處理是由.catch()完成的,現(xiàn)在我們都在使用 promises。
你甚至可以通過(guò)axios.all發(fā)起多個(gè)并發(fā)請(qǐng)求,比如說(shuō)你想一次性得到兩天的天文圖片可以這樣做:
- 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);
- });
異步代碼很容易地變得十分復(fù)雜并且不容易處理, Axios很輕松的解決了這個(gè)問(wèn)題,從長(zhǎng)遠(yuǎn)看來(lái)可以使你的開(kāi)發(fā)工作變得輕松。
SuperAgent
與Axios類(lèi)似,SuperAgent 是另一個(gè)流行的庫(kù),主要用于瀏覽器中的Ajax請(qǐng)求,但也適用于Node.js。使用以下命令安裝SuperAgent :
- npm install superagent@3.5.2
SuperAgent最酷的地方是能進(jìn)行鏈?zhǔn)秸{(diào)用,你可以把其它函數(shù)鏈到像query()這樣的請(qǐng)求上,并且添加參數(shù)。在前面的例子中我們都是手動(dòng)添加它們。請(qǐng)注意 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響應(yīng),這非???。
Got
如果你想用一個(gè)更輕量級(jí)的庫(kù),Got是另外一個(gè)選擇。它也可用于Twilio Functions。
再來(lái)一遍,實(shí)用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);
- });
如果你想要一個(gè)不像Request那樣臃腫的輕量級(jí)的庫(kù),使用Got就對(duì)了。
***的想法
以上并不是全部的解決方案,不過(guò)看到了這里,你知道了在Node.js中一些流行的HTTP庫(kù)中的基本功能是怎樣工作的。還有一些庫(kù),例如node-fetch將瀏覽器的獲取(fetch)功能移植到后端。在其他語(yǔ)言中也有各種類(lèi)似的庫(kù)解決這個(gè)問(wèn)題,比如 Python 和 Ruby 。