{%hackmd /au2gfdvHR0mEjvR_NzROqA?both %} ###### tags: `JavaScript` [AJAX] POST API 講解 === [TOC] ## 網路請求種類介紹 (HTTP 請求方法) > [HTTP 請求方法](https://developer.mozilla.org/zh-TW/docs/Web/HTTP/Methods) - 常見的 HTTP 請求方法 - `GET` :取得資料 - `POST` :傳送資料給對方(EX:傳送使用者資料,讓伺服器做驗證並回傳結果) - `PUT` :取代指定的資料 - `DELETE` :刪除資料 ## POST 網路請求文件介紹 :::info 一般公司的 API 文件也是長這樣,但裡面的屬性會多上不少 ::: > [練習用 API 網址](https://github.com/hexschool/nodejs_ajax_tutorial) ### 請求文件介紹 > ![請求文件範例](https://i.imgur.com/LLlH96q.png) > <small>請求文件範例</small> 網路請求功能 (API) 的文件中,會有的資訊 - Methods:URL 使用的 HTTP 請求方法(EX:`GET`、`POST`、...) - URL:發出請求的網址,傳送資料的對象 - Data:傳送給對方的資料格式,要包含正確的屬性。 - Success Response:如果伺服器驗證成功,會回傳的資料。 - Error Response:如果伺服器驗證失敗,會回傳的資料。 ### 伺服器收到請求後,會驗證的資訊 - URL:是否依循**正確的網址格式**,並使用**指定的請求方法**。 - Data:傳送的資料**格式或屬性**是否正確 - `resquest`的`data`屬性就是使用傳送的 Data。 ## 四種常見的 POST 請求 Content-Type 介紹 - 傳送資料給伺服器時,建議註明 data 的格式 (Content-Type)。 - 串接別人的 API 時,要看清楚 data 的寫法,以及支援哪種資料格式。 ### 請求資料格式 (Request Header Content-Type) - application/x-www-form-urlencoded - 使用 HTML 的原生 `form` 表單發出 POST 請求格式。 - 在表單 `form` 中,按下 `submit` 按鈕,將資料傳送到 `action` 指定的網址。 > ![](https://i.imgur.com/m4gW2MO.png) > <small>按下 `submit`,將資料傳送到 `action` 指定的網址</small> - application/json - 傳送格式為 JSON 格式 - axios 預設的格式是 JSON 格式,可自行改為其他資料格式。 - multipart/form-data - 傳送檔案用的格式,例如圖片、PDF、word、MP4 等。 - text/plain - 記事本格式,較少用到。 ## 透過 axios 實做註冊 POST 網路請求 範例目標:使用練習用的 API 網址,用 axios 發出 POST 請求,進行註冊。 - `.post()` :使用 POST 請求。 - 第一個參數:API 網址,網址要寫對。 - 第二個參數:要給伺服器的 data,可存在變數,格式要依循文件要求。 - `.then()`:伺服器驗證成功時,會回傳資料。 - `.catch()`:伺服器驗證失敗,會顯示錯誤訊息。 ```javascript= let obj = { email: "abc@ggg.com", password: "ewrwerwer" }; axios .post("https://hexschool-tutorial.herokuapp.com/api/signup", obj) .then(function(res) { console.log(res); }) .catch(function(err) { console.loc(err); }); ``` > ![](https://i.imgur.com/Dx6Sifl.png) > <small>Success,帳號註冊成功</small> > ![](https://i.imgur.com/G1n8cEp.png) > <small>API 文件中 Success Response 對應 response 的 data</small> > ![](https://i.imgur.com/FtzzG5V.png) > <small>Errors,帳號已被註冊</small> ## 從 Chrome 觀察 POST 請求 ### 為什麼要了解 Chrome 的底層運作 - 熟悉除錯工具,遇到錯誤才知道如何去修改。 - 發出請求後,過程發生了什麼事情。 ### 從開發者工具 Network 看請求 > ![Network Type](https://i.imgur.com/4LCwpS1.png) > <small>從 Network 中觀察 Type</small> 為何 Name 是 Signin? - 因為使用的 URL 為 `https://hexschool-tutorial.herokuapp.com/api/signin` - 以最後的 `/signin` 為 Name 紅框中,同名字的請求出現兩個: - preflight - 先嘗試能否跨網域讀取,如果可以就實際發出請求 (xhr)。 - 不是每個瀏覽器都會呈現 preflight。 - xhr - 透過 JS 發出的網路請求。 - **會回傳真正資訊**。 點擊 xhr 請求看裡面的內容,會看到 Headers 分頁裡面有 Request Payload。 - Request Payload 就是要傳送的 data - 以 application/json 格式傳遞 POST 請求給對方伺服器時,data 會被放在這裡傳送。 > ![xhr headers](https://i.imgur.com/5bU4Yht.png) > <small>Request Payload</small> 而 Response 分頁,則可以看到伺服器回傳的 response data,內容跟我們使用 axios POST 請求時,`console.log(res.data)` 的內容相同。 > ![response data](https://i.imgur.com/7FgKB0b.png) > <small>response</small> ## 實做 axios DOM 表單註冊流程 :::danger 強烈推薦邊寫邊測試 像是用 JS 抓取 DOM 這個階段,抓完 DOM 後使用 console.log 看是否有抓到正確的DOM ::: > [本小節 Codepen 範例程式碼](https://codepen.io/hexschool/pen/jOVgyPr?editors=1010) 步驟 - 建立 HTML 表單,包含帳號密碼的輸入框,以及送出按鈕。 - 在 JS 抓取 DOM,並為送出按鈕註冊點擊監聽事件。 - 點擊按鈕後 - 先確認輸入框中是否都有值。 - 取得輸入框的值,並依文件要求的格式,將值放到物件 `obj` 裡面。 - 透過 axios 發出 POST 請求 - 將 `obj` 發送到伺服器驗證、等待回傳結果。 - 如果成功,可依回傳結果判斷要呈現的訊息,並且清空輸入框。 - 如果失敗,則顯示錯誤訊息。 HTML ```htmlembedded= <label>帳號:</label> <input class="account" type="text"/> <br/> <label>密碼:</label> <input class="password" type="password"/> <br/> <input class="send" type="button" value="送出"/> ``` JS ```javascript= const account = document.querySelector(".account"); const password = document.querySelector(".password"); const send = document.querySelector(".send"); send.addEventListener("click", function (e) { callSignUp() }); function callSignUp() { if (account.value == "" || password.value == ""){ alert("請填寫正確資訊") return } let obj = {}; obj.email = account.value obj.password = password.value axios .post("https://hexschool-tutorial.herokuapp.com/api/signup", obj) .then(function (res) { if(res.data.message == "帳號註冊成功") { console.log("恭喜帳號註冊成功") } else { console.log("帳號註冊失敗,有可能有人用你的email註冊!") } account.value = "" password.value = "" }) .catch(function (err) { console.loc(err); }); } ```