LINE Bot聊天機器人程式開發教學(五):使用Promise風格的request-promise讀取資料開放平臺的天氣品質JSON資料

這篇文章跟Line聊天機器人程式沒有直接關係。本文將說明如何使用Node.js的request以及request-promise模組,讀取行政院環境保護署,環境資源資料開放平臺空氣品質指標(AQI)數據,下一篇文章再將它整合到Line聊天機器人程式。

request模組是個簡單易用的HTTP請求前端物件,從它的專案介紹網頁的第一個範例,可知它有多簡單:

使用request模組連線google首頁

當request接收到伺服器的回應時,回呼函式將被觸發,並把回應內容傳給回呼函式的body參數

我們已經在「LINE Bot聊天機器人程式開發教學(四):佈署與測試Echo Bot」這篇文章的package.json檔設定安裝request模組,假設此程式檔名為req.js,執行結果如下,它將傳回Google首頁的HTML內容:

request傳回Google首頁的HTML內容

即時空氣品質指標的JSON格式數據位於這個網址:http://opendata2.epa.gov.tw/AQI.json

使用request讀取該JSON數據的範例程式如下,request的第一個參數改成名叫opts的自訂物件,請求網址放在uri屬性、另一個json屬性要設成true

opts自訂物件

此程式將在終端機顯示所有空氣檢測站的數據:

在終端機顯示所有空氣檢測站的數據

空氣品質指標AQI數據JSON格式

環境資源資料開放平臺的空氣品質指標,把所有觀測站的資料包在一個陣列中,底下是其中一個位於「臺中市」的「西屯」觀測站的數據:

「臺中市」的「西屯」觀測站的JSON數據

底下的request程式將搜尋並取出JSON資料裡的「西屯」觀測站數據:

取出JSON資料裡的「西屯」觀測站數據的request

完整的程式碼如下:

程式執行結果:

使用Promise處理非同步程序

上文的request模組使用「回呼函式」執行非同步任務。「LINE Bot聊天機器人程式開發教學(三):建立Node.js版的Echo Bot」這一篇文章使用的Line程式庫則採用稱為Promise(直譯為「承諾」)的非同步程式設計風格。這兩種非同步程式語法的差別在於,一個是把回呼函式嵌套在處理函式裡面(如下圖左),另一個則是用“.then”指令,串連回應函式(註: “then”有「然後…」之意):

兩種非同步程式比較

假設我們要撰寫一個「擷取網路資料、整理收到的資料之後,寫入磁碟檔案」這樣的程式,由於擷取網路和寫入檔案,都需要非同步處理,而且要依照順序執行兩大步驟,用「回呼函式」寫成的架構如下:

回呼函式

使用Promise風格的寫法則是:

Promise風格

回呼函式和Promise程式都能分成數行來寫:

分成數行的回呼函式和Promise程式

隨著函式增加、程式變得複雜,層層嵌套的回呼函式將導致程式不易閱讀和管理,老外用“callback hell”(回呼地獄)來形容這種情況。雖然程式功能一樣,但Promise風格的程式碼更清晰。Promise也被納入ECMAScript 6語言標準

使用request-promise模組向伺服器請求資料

request-promise模組是基於request模組,改用Promise風格的HTTP請求前端物件,程式基本架構如下:

Promise風格的程式基本架構

就像海誓山盟的諾言,承諾有可能無法兌現,執行Promise(承諾)敘述若成功的話,”then()”當中的回應函式就會被執行;若承諾無法履行,則執行“catch()”裡的函式。

海誓山盟

改用request-promise模組取得「西屯」觀測站空氣品質指標數據的完整程式碼如下:

延伸閱讀

2 thoughts on “LINE Bot聊天機器人程式開發教學(五):使用Promise風格的request-promise讀取資料開放平臺的天氣品質JSON資料

  1. 老师,您好 我还是想问下 超图解Arduino互动入门设计 中用dht11远程监控温湿度值 中的硬件连线问题 我对其中以太网卡的使用不太清楚 我用学校的宽带线插在以太网卡上 然后让笔记本用手机热点上网 无论怎么打网页 网页都打不开192.168.1.25这个网址 想问下老师 知不知道是哪里的原因 如果我表述的不清楚 我之后给老师您发图片 万望老师百忙之中抽空解答 不胜感激!

    1. 从笔记本开放热点给其他设备上网,这些连接设备所处的网路和你的笔记本分属于不同的局域网,所以不能互连。而且那些连接笔记本热点的装置,估计都是用DHCP,不是固定IP。

      若要测试连线,你可以用另一个装置(例如:手机),连上同一个笔记本的热点,这样一来,手机和Arduino就位于相同网域,可以相互连接。

      假设你用的是Windows 10,从「行动热点」画面就能看到目前连接的装置名称和IP地址。

      thanks,
      jeffrey

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *