昨天我們先帶大家簡單認識 Node.js 是甚麼和它在使用上的優勢與便利後, 今天要來看看該怎麼應用 Node.js!
我們將使用 Node 來運行 Javascript 作為服務器端的程式碼。 並且使用 Express 等模組 (module)
, 實作 forward-facing APIs
就如同我們之前一直在使用的 AJAX fetch 的 API 一樣。
我們將定義 API 端點 (API endpoints)
, 然後提供在有人從該端點請求時應該運行的程式碼。如此一來, 我們就可以讀取他們的 query 參數
並用相關數據進行響應 (respond)
。
啟動 Node.js 應用程序有幾個步驟, 但大多數的項目還是遵循相同的結構。
使用 Node.js 時,你主要會使用 command line
來操作。
node-practice
)npm init
來初始化一個 package.json 配置文件 (configuration file), 你可以一直按 Enter
來使用預設值 (defaults)npm install <package-name>
安裝任何模組 (modules)app.js
)在此過程中, npm 這個工具將幫助你安裝
和管理
你在 Node 應用程序中有用的套件 (packages)
npm install express
或 npm install express
--``save
安裝 Express.js 包, 成功安裝 Express 後會自動被存到 package.json 中。What is Express?
http://expressjs.com/
Express4.18.1
→ Fast, unopinionated, minimalist web framework for Node.js
當你使用 Node.js 運行 .js 文件時, 你可以訪問 JS 中的預設函數(例如 console.log)。
而為了獲得 file i/o 或處理網路請求等功能, 你需要從模組中引入該功能 - 類似於在 Java 或 Python 中使用的 import 這個關鍵字。
在 Node.js 中, 你可以使用 require() 函數
來執行此操作, 並傳遞要引入的模塊的字符串名稱 (string name)。例如, 我們在 Node.js 中用於響應(respond) HTTP 請求的模組稱為 express。
就可以像這樣引入 Express:
const express = require("express");
實作一個簡單的 "Say hi to Pig Lin!” Express application
const express = require('express'); // 引入 library
const app = express(); // express 引入一個 function
// deal with different requests
// 參數: url, 要執行的function
app.get("/posts", function (req, res) {
res.type("text").send("Say hi to Pig Lin!");
});
app.get("/pig", function (req, res) {
res.send("Oink Oink!");
});
// 運行 8080 port
app.listen(8080); // 選擇使用一個不易產生衝突的 port
於瀏覽器輸入 http://localhost:8080/posts
, 你就可以看到 server 回傳的文本內容:
於瀏覽器輸入 http://localhost:8080/pig
:
app.get(...) | 處理 GET 請求的方法 |
---|---|
app.post(...) | 處理 POST 請求的方法 |
req (慣例名稱) | 請求物件: 有權存取請求參數等項目 |
res (慣例名稱) | 響應物件: 具有向客戶端發送數據的方法 |
res.type(...) | 設置“content-type”, 始終會在你的response中設置“text/plain”或“application/json” |
res.send(response) | 將response發送給客戶端 |
res.json(response) | 與 res.send 相同, 不同的是這邊使用 JSON 物件 |
當我們要啟動 localhost 服務器以運行 Express 應用程序時, 你需要指定要監聽的 port (端口)。
express app 物件有一個函數 app.listen
, 它接受一個端口號(port number)
和 callback 函數 (optional)
當參數。
另外在 app.js 的底部, 添加以下程式碼 - (當託管在實際的服務器上時, 需要 process.env.PORT
才能使用預設的端口)。
// 允許我們通過設置環境去輕鬆更改端口變數 (port variable)
const PORT = process.env.PORT || 8080;
app.listen(PORT);
routes 用於定義 Web 服務中的端點們
Express 支持不同的 HTTP 請求 — 而我們將學習 GET 和 POST 並且 Express 會嘗試按照你在程式碼中定義的順序匹配 routes。
GET
app.get(path, (req, res) => {
...
});
app.get
允許我們創建一個 GET 端點。 它有兩個參數: 端點 URL 路徑
, 以及用於修改/發送響應的 callback 函數
。
向路徑添加路由(Routing)時, 你可以從請求中檢索訊息, 並使用 res
發送回響應(例如: 設置 status code、content-type 等); 然而, 如果訪問的端點在你的 Express 應用程序中沒有匹配的路由, 則響應將是 404(找不到資源)。
關於 Request 的屬性與方法:
名稱 | 描述 |
---|---|
req.params | 來自 request 的端點"路徑"參數 |
req.query | 從 request 中"查詢"參數 |
關於 Response 的屬性與方法:
名稱 | 描述 |
---|---|
res.status( ) | 設定 response status code |
res.sendStatus( ) | 使用預設狀態文本設定 response status code |
res.set( ) | 設定 header 訊息, 例如: “content-type” |
res.type(...) | 設置“content-type”, 始終會在你的response中設置“text/plain”或“application/json” |
res.send(response) | 將response發送給客戶端 |
res.json(response) | 與 res.send 相同, 不同的是這邊使用 JSON 物件 |
res.write(data) | 在 response 中寫入 data 而不結束交互通訊 |
在一般默認的情況下, 響應 (response) 的內容格式是 HTML, 儘管在我們的 Web 服務中, 我們只會發送純文本 (plain text)
或 JSON 響應
。要更改內容格式的話, 可以使用 res.set 函數
, 該函數用於設置 response header 訊息(例如: 內容格式)。
你也可以使用 res.type("text")
和 res.type("json")
, 它們分別相當於設置 text/plain
和 application/json
Content-Type headers。
設定 content-type 為 text/plain
app.get('/hello', function (req, res) {
// res.set("Content-Type", "text/plain");
res.type("text"); // 如同上一行的 res.set 寫法
res.send('Hello Pig Lin!');
});
設定 content-type 為 application/json
app.get('/hello', function (req, res) {
res.set("Content-Type", "application/json");
res.json({ "msg" : "Hello Pig Lin!" });
});
使用 :param
定義路由參數, 在路由中充當通配符(wildcards)
, 讓使用者將"變數(variable)"傳遞給端點。
Route path: /countries/:country/cities/:city
Request URL: http://localhost:8080/countries/TW/cities/Taipei
req.params: { "country": "TW", "city": "Taipei" }
以上資訊會附加到請求物件, 可以使用 req.params
來訪問
app.get("/countries/:country/cities/:city", function (req, res) {
res.type("text");
res.send("Send a request for " + req.params.city + ", "
+ req.params.country);
});
你也可以使用 req.query
物件在 Express 中使用 query 參數
:
與路徑參數 (path parameters) 不同
, 這些不包含在路徑 string 中(使用 Express 路由來匹配), 我們無法確定訪問的 query key 是否存在。如果路由需要的參數遺失了, 應該在響應中向客戶端發送錯誤。
Route path: /cityInfo
Request URL: http://localhost:8080/cityInfo?country=TW&city=Taipei
req.query: { "country": "TW", "city": "Taipei" }
app.get("/cityInfo", function (req, res) {
let country = req.query.country; // TW
let city = req.query.city; // Taipei
// do what you want with variables in the response
});