###### tags: `JavaScript` # AJAX ## 使用流程說明 1. 建立 AJAX 物件 2. 傳送到對方伺服器要資料 3. 伺服器回傳資料到瀏覽器 4. 拿到資料做渲染或是加工處理 ### 1. 我們建立一個 XMLHttpRequest() 物件,來用 console 看 xhr 變數裡面存放了哪些東西 ```javascript= var xhr = new XMLHttpRequest(); ``` ![](https://i.imgur.com/QsoWnFV.gif) >[color=red] 重點是 readyState 的數字 readyState 數字 | 代表涵義 | --- | --- 0 | 你已產生一個 XMLHttpRequest,但還沒有連結你要撈的資料 | 1 | 你用了 open(),但你還沒有把資料送過去 | 2 | 偵測到你有用 send() | 3 | loading 中,有可能資料太大 | 4 | 你撈到資料了,數據已經完全鳩收到 | --- ### 2. open() - 連結遠端外部資料 - xhr.open('格式', '讀取的網址', '同步與非同步') 格式 | 代表涵義 | --- | --- get | 讀取資料 | post | 傳送資料到伺服器 | 同步與非同步 | 代表涵義 | --- | --- true | 非同步,不會等資料傳回來,程式碼會繼續往下跑,等到資料回傳才會自動回傳 | fales | 同步,等資料傳回來,才會讓程式碼會繼續往下跑 | ```javascript= xhr.open('get','https://hexschool.github.io/ajaxHomework/data.json',true) ``` - 因為使用 open() 所以 readyState 為 1 ![](https://i.imgur.com/isdMEwO.gif) --- ### 3. send() - 傳送資料 ```javascript= // 我們目前只要讀取,所以傳空值(null)給伺服器就好 xhr.send(null) ``` - 因為使用 send() 所以 readyState 會從 2 偵測到 send() 在到 3 讀取資料 完成讀取後回傳資料 readyState 到 4 - 從下圖可知資料已經從伺服器取回來,response 已經有資料 ![](https://i.imgur.com/EhQ6Zqu.gif) --- ### 4. 取得資料 - 非同步 true 你會發現用非同步他的資料會是空的,是因為程式碼跑的速度很快,根本來不及等資料回傳你的 console 就會先被打印出來了 ![](https://i.imgur.com/0S3n2BC.png) ```javascript= var xhr = new XMLHttpRequest(); xhr.open('get','https://hexschool.github.io/ajaxHomework/data.json',true) xhr.send(null) console.log('xhr資料:',xhr.responseText); ``` 這時候可以用 xhr 裡面的 onload 方法取得資料 ![](https://i.imgur.com/K5r8I30.png) ```javascript= var xhr = new XMLHttpRequest(); xhr.open('get','https://hexschool.github.io/ajaxHomework/data.json',true) xhr.send(null) xhr.onload = function(){ console.log('xhr資料:', xhr.responseText); } ``` 再用 JSON.parse 將字串轉成物件傳送到畫面 ![](https://i.imgur.com/GKZALWR.png) ```javascript= <span class="text"></span> <script> var xhr = new XMLHttpRequest(); xhr.open('get','https://hexschool.github.io/ajaxHomework/data.json',true) xhr.send(null) xhr.onload = function(){ var str = JSON.parse(xhr.responseText) document.querySelector('.text').textContent = str[0].name } ``` - 同步 fales 使用同步就可以先取得資料了,但是資料量太大可能會等很久造成使用者體驗降低 ![](https://i.imgur.com/M4jqMFe.png) ```javascript= var xhr = new XMLHttpRequest(); xhr.open('get','https://hexschool.github.io/ajaxHomework/data.json',false) xhr.send(null) console.log('xhr資料:', xhr.responseText); ``` 再用 JSON.parse 將字串轉成物件傳送到畫面 ![](https://i.imgur.com/wY1WHTj.png) ```javascript= <span class="text1"></span> <script> var xhr = new XMLHttpRequest(); xhr.open('get','https://hexschool.github.io/ajaxHomework/data.json',false) xhr.send(null) var str = JSON.parse(xhr.responseText) document.querySelector('.text1').textContent = str[0].name </script> ``` ## HTTP 狀態碼 狀態碼 | 代表涵義 | --- | --- 200 | 成功 (OK) | 3XX | 重新導向 (Redirection) | 404 | 找不到檔案或目錄 | ## Cross-Origin Resource Sharing (CORS) 跨來源資源共用(Cross-Origin Resource Sharing (CORS))是一種使用額外 HTTP 標頭令目前瀏覽網站的使用者代理 (en-US)取得存取其他來源(網域)伺服器特定資源權限的機制。當使用者代理請求一個不是目前文件來源——例如來自於不同網域(domain)、通訊協定(protocol)或通訊埠(port)的資源時,會建立一個跨來源 HTTP 請求(cross-origin HTTP request)。 基於安全性考量,程式碼所發出的跨來源 HTTP 請求會受到限制。例如,XMLHttpRequest 及 Fetch 都遵守同源政策(same-origin policy)。這代表網路應用程式所使用的 API 除非使用 CORS 標頭,否則只能請求與應用程式相同網域的 HTTP 資源。 簡單來說就是在同一個網域下 API 可以隨意使用,但是如果在不同網域下要看對方的後端是否有開啟 CORS 如果沒有開啟會出現下方的錯誤訊息。 ![](https://i.imgur.com/RPwzfCc.png) 測試 CORS 網址:http://www.test-cors.org/ ![](https://i.imgur.com/We1Ok0d.png) ## AJAX - 2 種傳送方式 - 傳統傳送方式 - JSON傳送方式 這2種的程式碼差別在 - 表單輸入格式 setRequestHeader 的 application/ 後面不同 - 用 send 傳送 value 方式不同 ### AJAX 傳統傳送方式 ```javascript= <form action="index.html"> 帳號: <input class="email" type="text" name="email" id=""> <br> 密碼: <input class="password" type="password" name="password" id=""> <br> <input class="send" type="submit" value="send"> </form> <script> var xhr = new XMLHttpRequest(); var send = document.querySelector('.send') var text = document.querySelector('.text') send.addEventListener('click', function(e){ e.preventDefault() var emailVal = document.querySelector('.email').value var passwordVal = document.querySelector('.password').value xhr.open('post','https://hexschool-tutorial.herokuapp.com/api/signup',true) // 表單輸入格式 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded") xhr.send(`email=${emailVal}&password=${passwordVal}`) xhr.onload = function(){ var msg = JSON.parse(xhr.response) text.textContent = msg.message } }) </script> ``` ### AJAX JSON傳送方式 ```javascript= <form action="index.html"> 帳號: <input class="email" type="text" name="email" id=""> <br> 密碼: <input class="password" type="password" name="password" id=""> <br> <input class="send" type="submit" value="send"> </form> <script> var xhr = new XMLHttpRequest(); var send = document.querySelector('.send') var text = document.querySelector('.text') send.addEventListener('click', function(e){ e.preventDefault() var data = { email: document.querySelector('.email').value, password: document.querySelector('.password').value, } xhr.open('post','https://hexschool-tutorial.herokuapp.com/api/signup',true) // 表單輸入格式 xhr.setRequestHeader("Content-type","application/json") xhr.send(JSON.stringify(data)) xhr.onload = function(){ var msg = JSON.parse(xhr.response) text.textContent = msg.message } }) </script> ``` 不論是傳統還是 JSON 方式傳送結果都會一樣,需依照後端工程師的需求來使用 ![](https://i.imgur.com/PD4PHuZ.gif)