Skip to content

JavaScript 學習筆記 - Ajax

Intro

為了深入學習 JavaScript,不能單單只是會使用 Ajax ,而應進一步探討 Asyncronous JavaScript And XML(不過大多數的 XML 都已被 JSON 取代)。

首先看懂 Ajax(Asyncronous JavaScript And XML) 是什麼

Ajax 定義

結論放前面,Ajax 就是:

向 server 發送請求之後,可以不需等待結果,就先進行其他的任務。等 server 回傳結果,再行處理。

為什麼需要 Ajax?

稍微了解 JavaScript 的人都明白,瀏覽器在讀取 JS 檔案時是一行接著一行讀取的,當一行程式碼還沒處理完畢,就不會去動下一行,也因此一行卡住了,所有人都會等它,這就是同步處理。

反之,你不確定這串程式碼會花多久時間,或你已經知道這會需要一段時間來處理,不想要網頁因為等待這串程式碼而卡住,就叫瀏覽器跳過去,先解讀其他程式碼,這就叫異步處理。

Ajax 就是為了完成異步處理(Asyncronous)而出現的手段。因為要呼叫 server 再得到回傳資料,你實在無法確定這會花多少時間,所以乾脆讓它在背景處理好之後再渲染到 DOM。

延伸應用,這也能夠提升使用者體驗。舉例來說,當使用者做了某個動作,網頁上的某部分資料會變動,透過 Ajax 就不需要切換整份 HTML,而只要替換變動的那部分資料就好,這才是符合使用者體驗的行為。

是不是很方便呢?

那麼,到哪裡才買得到呢?

不是啦,我是說,要怎樣才能使用如此方便的 Ajax?

XMLHttpRequest

第一種方式,就是透過原生的 JavaScript 去操作,一步步定義好每個 XMLHttpRequestmethodfunction,然後送出。

關於使用原生 JS 操作 XMLHttpRequest,可以參考我之前寫的 JavaScript 學習筆記 - XMLHttpRequest

JQuery

根據 從 ES6 開始的 JavaScript 學習生活 提供的範例,jQuery 在 Ajax 的操作中,提供了與操作 Promise 類似的作法。

範例如下:

js
$.ajax({
    // 進行要求的網址(URL)
    url: './sample.json',
    // 要送出的資料
    data: {
        id: 'a001'
    },
    // 要使用的 method
    type: 'GET',
    // 資料的類型
    dataType : 'json',
})
  .done(function( json ) {
       // 要求成功時要執行的程式碼
      })
  .fail(function( xhr, status, errorThrown ) {
       // 要求失敗時要執行的程式碼
        console.log( '出現錯誤,無法完成!' )
        console.log( 'Error: ' + errorThrown )
        console.log( 'Status: ' + status )
        console.dir( xhr )
      })
  // 不論成功或失敗都會執行的程式碼
  .always(function( xhr, status ) {
    console.log( '要求已完成!' )
    });

老實說,我一直沒有去碰 jQuey,因為我覺得大部分時候,原生 JS 都能解決,因此一直在加深原生的基礎。

Fetch

這是一個 HTML5 的新 API,而非 ES6 的新語法。但同時, 它也會需要使用到 ES6 的 Promise 來實作。

Fetch 如果成功的話,會回傳一個帶 response 的 Promise 物件。它的語法類似於 jQuery,但相較之下更單純:

js
fetch( url, {method: 'get'} )
    .then(function(response) {
        // 在這裡處理 response
    })
    .catch(function(err) {
        // 丟出 Error :(
    });

不過要注意的是, Fetch 只要收到回應,都會回傳 Promise,因此需要多加注意分辨成功與失敗的狀態。

ES6 Promise

既然 Fetch 就是會回傳一個 Promise,那麼至少必須了解如何使用 Promsie。

直接透過範例來看會更好懂:

js
let promise = new Promise(function(resolve, reject){
    // 異步處理
    // 處理完後,調用 resolve 或 reject
});

// 或者這樣做
fetch( url, {method: 'get'} ) //這裡會傳回 promise
    .then(successCallback)
    .catch(errorCallback);

簡單地說,Promise 的操作,就是用 .then 與 .catch 去對成功與失敗的結果分別調用 callback。

Async Await

既然有了實現異步處理的工具,再來就會渴求更多。如果能夠「指定」處理的順序,那當然再好不過了對吧!

在認識 async 以前,我如果要設定處理順序,就會在「需要優先處理的 function」內包覆一個 callback,這樣在優先處理完 function 之後,才會去調用那個 callback,繼續處理接下來的部分(這樣寫又複雜又有機會出 bug)。

但只要在 function 前加上 async,就不需要再寫 callback!只要在需要優先處理的 function 前加上 await,所有程式就都會等這個 function 處理完之後,才繼續執行。

換句話說,async 會將 function 內的某部分程式碼變為「強迫單線程執行」。

綜合以上的這些技術與知識,是不是覺得更能輕鬆實作 Ajax 了呢?