這篇文章跟Line聊天機器人程式沒有直接關係。本文將說明如何使用Node.js的request以及request-promise模組,讀取行政院環境保護署,環境資源資料開放平臺的空氣品質指標(AQI)數據,下一篇文章再將它整合到Line聊天機器人程式。
request模組是個簡單易用的HTTP請求前端物件,從它的專案介紹網頁的第一個範例,可知它有多簡單:
當request接收到伺服器的回應時,回呼函式將被觸發,並把回應內容傳給回呼函式的body參數。
我們已經在「LINE Bot聊天機器人程式開發教學(四):佈署與測試Echo Bot」這篇文章的package.json檔設定安裝request模組,假設此程式檔名為req.js,執行結果如下,它將傳回Google首頁的HTML內容:
即時空氣品質指標的JSON格式數據位於這個網址:http://opendata2.epa.gov.tw/AQI.json
使用request讀取該JSON數據的範例程式如下,request的第一個參數改成名叫opts的自訂物件,請求網址放在uri屬性、另一個json屬性要設成true:
此程式將在終端機顯示所有空氣檢測站的數據:
空氣品質指標AQI數據JSON格式
環境資源資料開放平臺的空氣品質指標,把所有觀測站的資料包在一個陣列中,底下是其中一個位於「臺中市」的「西屯」觀測站的數據:
底下的request程式將搜尋並取出JSON資料裡的「西屯」觀測站數據:
完整的程式碼如下:
var request = require('request'); const SITE_NAME = '西屯'; const opts = { uri: "http://opendata2.epa.gov.tw/AQI.json", json: true }; request(opts, function (error, response, body) { if (!error && response.statusCode === 200) { let data; for (i in body) { if (body[i].SiteName == SITE_NAME) { data = body[i]; break; } } console.log(data) } });
程式執行結果:
使用Promise處理非同步程序
上文的request模組使用「回呼函式」執行非同步任務。「LINE Bot聊天機器人程式開發教學(三):建立Node.js版的Echo Bot」這一篇文章使用的Line程式庫則採用稱為Promise(直譯為「承諾」)的非同步程式設計風格。這兩種非同步程式語法的差別在於,一個是把回呼函式嵌套在處理函式裡面(如下圖左),另一個則是用“.then”指令,串連回應函式(註: “then”有「然後…」之意):
假設我們要撰寫一個「擷取網路資料、整理收到的資料之後,寫入磁碟檔案」這樣的程式,由於擷取網路和寫入檔案,都需要非同步處理,而且要依照順序執行兩大步驟,用「回呼函式」寫成的架構如下:
使用Promise風格的寫法則是:
回呼函式和Promise程式都能分成數行來寫:
隨著函式增加、程式變得複雜,層層嵌套的回呼函式將導致程式不易閱讀和管理,老外用“callback hell”(回呼地獄)來形容這種情況。雖然程式功能一樣,但Promise風格的程式碼更清晰。Promise也被納入ECMAScript 6語言標準。
使用request-promise模組向伺服器請求資料
request-promise模組是基於request模組,改用Promise風格的HTTP請求前端物件,程式基本架構如下:
就像海誓山盟的諾言,承諾有可能無法兌現,執行Promise(承諾)敘述若成功的話,”then()”當中的回應函式就會被執行;若承諾無法履行,則執行“catch()”裡的函式。
改用request-promise模組取得「西屯」觀測站空氣品質指標數據的完整程式碼如下:
var rp = require('request-promise'); const SITE_NAME = '西屯'; const opts = { uri: "http://opendata2.epa.gov.tw/AQI.json", json: true }; rp(opts) .then(function (repos) { let data; for (i in repos) { if (repos[i].SiteName == SITE_NAME) { data = repos[i]; break; } } console.log(data); }) .catch(function (err) { console.log('出錯了~找不到指定資源…'); });
老师,您好 我还是想问下 超图解Arduino互动入门设计 中用dht11远程监控温湿度值 中的硬件连线问题 我对其中以太网卡的使用不太清楚 我用学校的宽带线插在以太网卡上 然后让笔记本用手机热点上网 无论怎么打网页 网页都打不开192.168.1.25这个网址 想问下老师 知不知道是哪里的原因 如果我表述的不清楚 我之后给老师您发图片 万望老师百忙之中抽空解答 不胜感激!
从笔记本开放热点给其他设备上网,这些连接设备所处的网路和你的笔记本分属于不同的局域网,所以不能互连。而且那些连接笔记本热点的装置,估计都是用DHCP,不是固定IP。
若要测试连线,你可以用另一个装置(例如:手机),连上同一个笔记本的热点,这样一来,手机和Arduino就位于相同网域,可以相互连接。
假设你用的是Windows 10,从「行动热点」画面就能看到目前连接的装置名称和IP地址。
thanks,
jeffrey
老師您好:
我輸入heroku open 會跳出瀏覽器也有看到Hello World!
可是輸入node req.js 卻出現
‘node’ 不是內部或外部命令、可執行的程式或批次檔
請問是為什麼?
因為你的電腦系統沒有安裝node.js
thanks,
jeffrey
老師你好,我在執行的時候都會出現亂碼的問題
後來我把編碼調成UTF-8格式,但不管是哪個地區都只會顯示 ” 出錯了~找不到指定資源… ”
還有甚麼地方是我遺漏掉的嗎@@?
欸…我在windows 10系統系統的命令列執行都沒有問題,請直接把程式佈署到heroku再測試。
thanks,
jeffrey
請問能否發個如何抓xml的資料的教學~~~?
使用與解析XML,在《超圖解物聯網IoT實作入門》第二章已經說明過了~
thanks,
jeffrey
老師您好
目前想用line chatbot接收使使用者傳的訊息
並存到monglab中但程式一直跑不過
//————————————————–
bot.on(‘message’, function(event) {
if (event.message.type === ‘text’) {
var msg = event.message.text;
// 將聊天資料轉成資料模型
var m = new Message(msg);
// 存至資料庫
m.save(function (err) {
if (err) {
console.log(err)
}else
console.log(‘success’)
});
}
});
//————————————————–
請問在主要程式部分這樣打有錯嘛!?
老師您好:
輸入node req.js 卻出現
‘node’ 不是內部或外部命令、可執行的程式或批次檔
但我的電腦系統有安裝node.js
應該是Node沒有加入系統路徑。
thanks,
jeffrey
請問輸入node req.js 出現
$ node req.js
internal/modules/cjs/loader.js:638
throw err;
^
Error: Cannot find module ‘request’
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:636:15)
at Function.Module._load (internal/modules/cjs/loader.js:562:25)
at Module.require (internal/modules/cjs/loader.js:692:17)
at require (internal/modules/cjs/helpers.js:25:18)
at Object. (C:\Users\405_2\desktop\linebot_basic\linebot\req.js:1
:15)
at Module._compile (internal/modules/cjs/loader.js:778:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
at Module.load (internal/modules/cjs/loader.js:653:32)
at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
at Function.Module._load (internal/modules/cjs/loader.js:585:3)
是哪邊出了問題嗎?
根據錯誤訊息:
Error: Cannot find module ‘request’
你的系統沒有安裝request模組。
thanks,
jeffrey
請問要如何安裝呢 試過很多方法都不行
由老師解答 謝謝
在你的專案資料夾內執行:
npm install request
thanks,
jeffrey
老師您好 在輸入node req.js出現
D:\tcim\heroku\linebot>node req.js
internal/modules/cjs/loader.js:888
throw err;
^
Error: Cannot find module ‘D:\heroku\linebot\req.js’
[90m at Function.Module._resolveFilename (internal/modules/cjs/loader.js:885:15)[39m
[90m at Function.Module._load (internal/modules/cjs/loader.js:730:27)[39m
[90m at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)[39m
[90m at internal/main/run_main_module.js:17:47[39m {
code: [32m’MODULE_NOT_FOUND'[39m,
requireStack: []
}
請問該如何解決呢
錯誤訊息’MODULE_NOT_FOUND’代表找不到程式用到的模組,請先安裝再執行。
thanks,
jeffrey