如何獲取 DOM 節點、串接 API,我們已經大概能了解,可是在網路這個大區域裡面,那些傳過來傳過去的過程似乎依然不是那麼簡單,於是我們今天還是要繼續討論那個過程,我感覺總之就是要把那些精髓都了解透徹了這一切才會結束,跟我感覺一樣的+1 (沒有人
接下來我要講的可能對很多人來說都是廢話,但我在學習的時候其實很常會突然忘記一些原理,因此這段廢話對之後回鍋來看文章的自己來說,其實還是有某種程度上的幫助。
學習寫網頁的時候,最開始會先學習 CSS 及 HTML,學習如何打造網頁的外觀及美化,接著便開始學習 JavaScript,讓網頁不再是靜態的,而是能夠真正的與使用者互動,除了能與使用者互動外還有最重要的一點就是與 Server 端的互動,也就是說必須學會從瀏覽器用 JavaScript 跟後端 Server 拿資料,否則我們的網頁會呈現一陳不變,它到變成化石(?)都只會是同一筆資料。
那麼為什麼前端一定要跟後端交換資料呢?舉個例子,假如今天我們要做一個職棒賽事的網站,這個網站理所當然必須隨著賽事的變化而變動,假如我們今天不從 Server 獲取資料,你喜歡的棒球隊如果一開場是 0,就會永遠的是 0 了 ( 喔不 ),因為資料會靜止不動,所以這也是為什麼我們必須與 Server 不斷交換資料的緣故。
而賽事的資料哪裡來?這個應該大家都很清楚,當然是中華職棒給的數據資料;那我們怎麼拿到這些資料?麥當勞服務員會送來給我們 ( 喂!!! )。
好啦,不鬧,我們可以透過中華職棒的 API 獲取資料,不知道大家還記不記得上一篇的麥當勞服務員?關於 API 如果想了解也可以去稍微看兩眼,這裡我就不再解釋 API 了。
在討論 AJAX 之前,我決定先討論 request 和 response,以免先討論 AJAX 的時候會提了一大堆的 request 和 response。
一般來說傳輸資料的兩端會分為「客戶端 ( Client )」和 「伺服器端 ( Server )」。
從上面的理論可以知道,網頁所呈現的圖片、資料,其實就是一大堆的 request 和 response 不斷來回傳輸。
要再瀏覽器上面發送 request,我們必須使用到 AJAX 這種技術,它的全名叫做「Asynchronous JavaScript and XML」,「Asynchronous」的意思即為非同步。
在說到什麼是非同步前,先來討論一下什麼是同步。JavaScript 幾乎都是同步執行的,意思是它執行到某一行的時候,會等這行執行完畢才執行下一行,它在執行程式碼的時候是照著順序的。
下面我們都會借用大神範例來討論,這個範例的意思是最後一行會過很長的時間才會執行:
var count = 10000000;
while(count--) {
// 做一些耗時的操作
}
// 等很久才被執行到
console.log('done')
如果這個情況用在網路執行操作的話感覺挺不妙的,為什麼呢?接著看底下的範例:
// 假設有個發送 Request 的函式叫做 sendRequest
var result = sendRequest('https://api.twitch.tv/kraken/games/top?client_id=xxx');
// 等很久才被執行到
console.log(result);
當 JavaScript 執行到 sendRequest
的時候,因為是同步的,必須等待 response 回傳才會繼續進行下一步,因此在 response 回傳之前,整個 JavaScript 都會是靜止不動的,這聽起來真的是很可怕對吧?
因此,如果運行的時候已經知道會很耗時間,或是執行的情況不太穩定的話,就必須注意不能使用同步的方式來執行。
非同步的意思則是執行完之後就放著,不需要等待回傳就繼續執行下一件事,如範例:
// 假設有個發送 Request 的函式叫做 sendRequest
var result = sendRequest('https://api.twitch.tv/kraken/games/top?client_id=xxx');
// 上面 Request 發送完之後就執行到這一行,所以 result 不會有東西
// 因為 Response 根本沒有回來
console.log(result);
另外要注意的地方是,非同步的 function 不能直接透過 return 回傳,因為以上面這個非同步的例子來說,他發送 request 之後就不會管它有沒有回傳,而直接進行下一步了,因此使用 ruturn 基本上也沒有 response 可以回傳。
如果要解決這個問題,可以使用 Callback Function ( 回呼函式 ),當非同步操作完成時,就可以呼叫這個 function,並把資料代進去:
// 假設有個發送 Request 的函式叫做 sendRequest
sendRequest('https://api.twitch.tv/kraken/games/top?client_id=xxx', callMe);
function callMe (response) {
console.log(response);
}
// 或者寫成匿名函式
sendRequest('https://api.twitch.tv/kraken/games/top?client_id=xxx', function (response) {
console.log(response);
});
Callback Function ( 回呼函式 ) 的概念有點像是,我拜託朋友幫我處理一些資料 ( 發送 request ),然後朋友請我先回家,因此我不用等他處理完給我 ( 不需要等待 response ),等朋友處理完之後便把資料帶來給我 ( response 回傳 )。
最後,還有一個東西還沒有提到,那就是 「XMLHttpRequest
」。XMLHttpRequest
是瀏覽器準備好讓我們能發送 request 的物件:
var request = new XMLHttpRequest();
request.open('GET', `https://api.twitch.tv/kraken/games/top?client_id=xxx`, true);
request.onload = function() {
if (request.status >= 200 && request.status < 400) {
// Success!
console.log(request.responseText);
}
};
request.send();
request.onload
意思是,指定當資料回來的時候,可以用哪一個 function 處理。
統整一下 AJAX 在實務上會怎麼呈現,傳統網頁是這樣的,我們可能點擊了一個標題,它就會開始全部更新,字體、顏色、區塊、資料訊息等等全部都會變成新的,開啟的是一個新的頁面,但是這樣的結果就是開啟的速度會變慢,因為他必須全部都重新跑過;而 AJAX 則可以是,我們同樣點擊了一個按鈕,但在同一個頁面他只更新了一個區塊,其他地方仍然是原本的,於是提高了網頁運行的效率。
參考資料:
輕鬆理解 Ajax 與跨來源請求
網路基礎 - HTTP、Request、Response