# [JavaScript] AJAX語法 ###### tags: `JavaScript` 即「Asynchronous JavaScript and XML」(非同步的JavaScript與XML技術),目前共四種串接方式[XMLHttpRequest、jquery](https://eyesofkids.gitbooks.io/javascript-start-from-es6/content/part4/ajax_fetch.html)、[Fetch](https://wcc723.github.io/javascript/2017/12/28/javascript-fetch/)、Axios 詳細介紹四類的不同:https://medium.com/dot-js/%E7%94%B1%E5%89%8D%E7%AB%AFrequest-%E7%9A%84%E5%B9%BE%E7%A8%AE%E6%96%B9%E6%B3%95-fbf8a0b4023a ## XMLHttpRequest * 其一老式做法 ── XMLHttpRequest ``` var xhr = new XMLHttpRequest(); xhr.open('get','URL',true); xhr.send(null); //傳送資料(若上面使用'get',則此欄填寫空值 null ) xhr.onload = function () { data = JSON.parse(xhr.responseText); console.log(`已經載入 api `) } ``` * 格式:'get'(讀取資料)、'post'(傳送資料至該資料庫) ### 同步與非同步 * true(預設值) 非同步 使用非同步的設定時,我們的程式碼不會等到資料回傳回來,就會開始執行後續程式碼,因為有時候我們撈取的 JSON 檔是一大筆資料,那等我們等一大筆筆資料抓完才去執行後續動作,網頁就會在載入完成之前都卡在那邊,無形中就會浪費許多時間成本,因此若要執行非同步,則需另設定一組函式來判定onload狀態,當onload完成後即可取得資料。 * false 同步 會等資料回傳(接收)完畢,才繼續往下跑 ### parse轉字串 其中有趣的是 data = JSON.parse(xhr.responseText); 因為 JSON 雖然本身是“陣列包物件”的格式,但資料在傳輸的時候必須轉換成 string(字串),所以我們在接收到了傳送來的「字串」時,就必須使用 JSON.parse 將其轉換回原本的格式 ### xmlHttp的5個狀態 * 得到xmlHttp對象的狀態: > var state = xmlHttp.readyState;//可能是0、1、2、3、4 > 0狀態:剛創建,還沒有調用open()方法; > 1狀態:請求開始:調用了open()方法,但還沒有調用send()方法 > 2狀態:調用完了send()方法了; > 3狀態:服務器已經開始響應,但不表示響應結束了! > 4狀態:服務器響應結束!(通常我們只關心這個狀態!!!) > * 得到服務器響應的狀態碼: > var status = xmlHttp.status;//例如為200、404、500 ## jQuery 實作影片一:https://bootcamp.15days.website/courses/fullstack-starter/lectures/9305400 完整呼叫ajax,可使用編譯器內建軟件,自動彈跳完整語法 ![](https://i.imgur.com/8Collm9.png) 直接使用post語法,簡化語法。 ![](https://i.imgur.com/H2QSUOJ.png) 實作影片二:https://www.youtube.com/watch?v=OtIOxstrhzY ``` $.ajax({ url: 'https://randomuser.me/api/', dataType: 'json', success: function(data) { console.log(data); // 取得的遠端資料 } }); ``` 實作影片三:https://www.youtube.com/watch?v=DxdTWIYqIzU ![](https://i.imgur.com/TF9sOkk.png) * 撈取回傳的資料如果是字串格式,需要使用JSON.parse方式轉為陣列 ![](https://i.imgur.com/WmLgTXB.png) * 取得JSON資料,使用判斷式加迴圈得出結果 codepen練習:https://codepen.io/vincer-chen/pen/GRoNzxY?editors=1010 ## Fetch 詳細資料:https://www.oxxostudio.tw/articles/201908/js-fetch.html 這裡提供一個簡單的範例來取得遠端的資料,這裡與 $.ajax 不同點在於: * fetch 會使用 ES6 的 Promise 作回應 * then 作為下一步 * catch 作為錯誤回應 (404, 500…) * 回傳的為 ReadableStream 物件,需要使用不同資料類型使用對應方法,才能正確取得資料物件。 ``` fetch('https://randomuser.me/api/', {}) .then((response) => { // 這裡會得到一個 ReadableStream 的物件 console.log(response); // 可以透過 blob(), json(), text() 轉成可用的資訊 return response.json(); }).then((jsonData) => { console.log(jsonData); }).catch((err) => { console.log('錯誤:', err); }); ``` Fetch目前使用上會一些缺點: * 對400,500都當做成功的請求,需要另外做處理,fetch() 回傳的 promise 物件, resolve 和 reject 的使用方式有差異, 當遇到 HTTP Status 404, 500 時會使用 resolve 但會將 status 的值從 ok 變為 false, reject 只有在網路發生錯誤或是任何會中斷網路請求時才會使用。 * 預設是沒有帶cookie,fetch 預設上不傳送或接收任何 cookies,如果網站依賴 session 會導致請求回傳未經認證,需要使用 cookies 必須額外設定 credentials。 * 不支援timeout handle * 不支援監測請求的進度 * 較早的瀏覽器並不支援(IE11以下不支援) ### 影片實作 影片來源:https://www.youtube.com/watch?v=ZNBwugL-u1o ![](https://i.imgur.com/JOomA7E.png) * 需要再執行第二次的then及result取得api裡的資料內容 * 經由response.json可以將從後端撈回的json字串格式轉為陣列的形式 ### Pormise與fetch實作解析 https://ithelp.ithome.com.tw/articles/10193346 ## Axios 我是在使用Vue.js時接觸到Axios的,Vue.js的作者Evan You 建議使用axios作為request的工具,使用axios的方式相當簡單,把axios引入就好了 ``` const result = document.querySelector('.result'); axios.get('https://randomuser.me/api/') .then(function (response) { let data = response.data; result.textContent = data.results[0].email; }) .catch(function (error) { // handle error console.log(error); }) .finally(function () { // always executed console.log('I always Execued'); }); ``` Axios 有下列幾個優點: * 簡單易用,使用方法類似於jQuery * 支持Promise API * 可以在node.js中使用 * 支援防CSRF * 提供併發請求 * 相當輕量,約13kb