# [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