--- tags: Node.js --- # Node.js 開 API (GET、POST、DELETE) ## API 是什麼 假設在前端有資料想在關閉瀏覽器後繼續使用,勢必要把資料存起來對吧? 既然要存資料,我們就需要將資料存到所謂的資料庫中,這時候就需要用到所謂的 API 了。 你可以理解為 API 是一個橋樑,用來連結前端與後端! ## 你要先知道的事 前端網頁無法直接與資料庫溝通,因為有安全問題,比如怕被有心人士竊取資料等等,所以必須通過後端才可以與資料庫聯繫。 整個流程大約是: 我們會從前端網頁發送請求給後端,然後後端就幫前端網頁存資料到資料庫裡面。 這邊後端可能會先驗證你是否有權限存資料、是否有傳資格過來、存的資料格式是否正確等等。 所以當後端處理過,確認一切都沒問題了,才會把資料存到資料庫中。 然後後端會再跑一次流程,比如確認資料庫內容是否存成功等等,最後才把資料回應給前端網頁。 - 請求是 request - 回應是 response - 常見的請求方式有: 1. GET - 我要資料 所以我發請求要某一個資料 2. POST - 我要寫資料到資料庫 我要發送資料到資料庫 3. PUT - 我要更新資料 4. PATCH - 我要更新資料 5. DELETE - 我要刪除資料 舉個例子來說: 我先 post 資料到資料庫,然後 get 就可以開始存取資料, 我想更新資料裡的內容就可以用 put patch,我要刪一筆資料就用 delete 請求。 不管哪種方法都是前端先發出請求給後端,後端才給回應。 這邊要注意:前端一定要先給請求,後端才能給回應。沒有請求,後端無法直接給回應!他們就是一組的! ## express ### express 環境建立 express 是 node.js 中很常見的輕型框架,它可以快速的產生一個環境,它需要通過 npm 來安裝,附上[官網連結](https://expressjs.com/zh-tw/starter/generator.html)。 步驟如下: 1. 在終端機中輸入 ```shell= $ npm install express-generator -g ``` 2. 輸入指令建立項目資料夾 ```shell= $ express --view=pug 項目資料夾名稱 ``` - 補充: `pug` `ejs` 為引擎 放在 `--view=` 後 這裡使用哪個都可以 看個人 3. 建立後 cd 到資料夾中 輸入指令安裝依賴包 ```shell= $ npm install ``` 4. 在終端機中輸入以下指令開始運行 node ```shell= $ npm start ``` - 預設的端口號 3000 在瀏覽器中輸入 http://127.0.0.1:3000/ 即可看到畫面 完成後就可以使用 vs code 編輯器開啟項目資料夾了 ### express 包含哪些東西 1. bin/www.js 是伺服器有關的配置 2. node_modules 是相關的依賴套件 3. public 公開檔案 如 html js css img 4. routes 路由設定 主要看 index.js 檔案 5. views 相當於 html 用來插入後端資源渲染頁面的 6. app.js 整個項目的進入點 會關聯到所有相關檔案 7. package.json 關聯 node_modules 的 裡面會寫出所有依賴項目 讓 npm install 知道依賴的資料夾有哪些 ## 測試 首先可以打開 views/index.ejs 隨便修改或添加值 然後重整 http://127.0.0.1:3000/ 頁面,會發現東西改變了,這邊更改的部分是前端,改了直接重新整理就生效。 接著我們打開 routes/index.js 修改傳入的 title 的值,然後重整 http://127.0.0.1:3000/ 頁面,會發現東西沒有變,這邊更改的部分就是屬於後端,在後端修改東西後,必須重新開啟服務器才會更新資料! - 補充: control + C 可關閉服務器 ### 在 vs code 中處理終端機需要一直關閉重啟的問題 點擊左側選單的下方圖片圖案 ![](https://i.imgur.com/2tYc0Xp.png) 然後點擊建立 launch.json 檔案 選擇 Node.js 然後就會看到左上角出現如下圖的東西: ![](https://i.imgur.com/HZQN0bN.png) 點擊播放按鈕會出現下方這個選單列: ![](https://i.imgur.com/CtFOaLY.png) 每次修改完後就點一下下方按鈕: ![](https://i.imgur.com/Xui9x8d.png) node 就會重啟了。 ## 關於路由的概念 可以想像在後端有許多的方法,在接收請求時需要知道這個請求對應到哪個方法。 路由表中的每個路由都會對應一個特定的方法 所以我們要先建立路由表 才能對應到特定的方法 ### 建立路由表 這邊我們複製一份 routes/index.js 取名叫 api.js 一樣放在 routes 的資料夾中 然後我們開啟 app.js 把新建立的 api.js 引入 新增代碼如下: ```javascript= var apiRouter = require('./routes/api'); ``` 引入後啟用它 一樣在 app.js 中撰寫 新增代碼如下: ```javascript= app.use('/api', apiRouter); ``` ### 建立 API 首先在同路徑可以對應到不同請求方法 比如路徑 `'/products'` 可以同時設置 GET POST 等請求 不會有問題。 然後講一下響應的部分有以下幾個常用方法: 1. res.send() - 傳入任何你想傳送的響應內容,用於發送響應給網頁 2. res.end() - 不傳入任何參數,用於結束當前響應 (沒結束網頁就會一直等待請求,一直轉圈圈) 3. res.status() - 傳入數字,用於傳送狀態碼 如 404 、 200 等 #### GET 請求 回到我們的 routes/api.js 中 此時 `router.get('/', function(rea, res, next){ ... })` 中的 `'/'` 就會對應到 `http://127.0.0.1:3000/api` 這個網址 然後我們改一下 把 `'/'` 改成 `'/products'` 現在要傳送請求與獲取響應就要使用 `http://127.0.0.1:3000/api/products` 了 這邊我們先建立一個 products 路徑的 GET 請求,自己撰寫一個 data ,然後把 data 響應給 GET 請求。 完整代碼如下: ```javascript= // 自行建立的 data const data = [{ id: 1, name: "小明" }]; // 設置請求路徑為 /products 請求方法為 get router.get("/products", function (req, res, next) { // 使用 res.send() 方法設置響應傳送 { success: true, data } // 使用 res.end() 方法結束響應 // 這裏可以直接在 send() 後 .end() 也可以換行寫 res.end() res.send({ success: true, data }).end(); }); ``` #### POST 請求 這邊我們建立一個 product 路徑的 POST 請求,用來新增一筆產品資料,主要過程就是需要把前端送過來的資料取出來,加到現有資料中。 完整代碼如下: ```javascript= // 設置請求路徑為 /product 請求方法為 post router.post("/product", function (req, res) { // req.body 是前端傳來的資料 const product = req.body; // 後端要處理新增 id product.id = new Date().getTime(); // 把資料加到 data 中 data.push(product); // 傳響應告訴前端已新增成功 res.send({ success: true, data }).end(); // console.log 看一下 data, 確認是否新增成功 console.log(data); }); ``` #### DELETE 請求 刪除的品項通常有兩種獲取方式: 1. 用 req 的參數獲取 2. 直接通過網址參數帶入品項的 id 這邊用網址方式做說明: 首先要建立一個 product 路徑的 delete 請求,這邊的請求路徑後方要帶入準備刪除的品項 id ,所以在撰寫路由時應該寫 `/product/:id` (這裏的 `:id` 表示傳入的是動態的內容,該內容為一個 id) 取得網址傳入的參數方法為 `req.params.id` 完整代碼如下: ```javascript= // 設置請求路徑為 /product/:id 請求方法為 delete router.delete("/product/:id", function (req, res) { // 首先通過 req.params.id 獲取傳入的 id const id = req.params.id; // 然後遍歷 data 找出 id 符合的那筆資料 將它刪除 data.forEach((item, key) => { if (item.id == id) { data.splice(key, 1); } }); // 最後傳送響應告訴前端已刪除成功 res.send({ success: true, data }).end(); }); ``` ## 補充 ### API 測試套件 1. Postman - 這是一個 APP 2. Thunder Client - 這是 VS Code 套件 ## 關於一些 Q&A api 與 restful api 差異: restful api 也是一個 api 只是它在建構時會遵循規則