iT邦幫忙

2021 iThome 鐵人賽

DAY 27
0
Modern Web

我的JavaScript日常系列 第 27

JavaScript Day 27. AJAX、Request、Response

如何獲取 DOM 節點、串接 API,我們已經大概能了解,可是在網路這個大區域裡面,那些傳過來傳過去的過程似乎依然不是那麼簡單,於是我們今天還是要繼續討論那個過程,我感覺總之就是要把那些精髓都了解透徹了這一切才會結束,跟我感覺一樣的+1 (沒有人

接下來我要講的可能對很多人來說都是廢話,但我在學習的時候其實很常會突然忘記一些原理,因此這段廢話對之後回鍋來看文章的自己來說,其實還是有某種程度上的幫助。

基礎觀念

學習寫網頁的時候,最開始會先學習 CSS 及 HTML,學習如何打造網頁的外觀及美化,接著便開始學習 JavaScript,讓網頁不再是靜態的,而是能夠真正的與使用者互動,除了能與使用者互動外還有最重要的一點就是與 Server 端的互動,也就是說必須學會從瀏覽器用 JavaScript 跟後端 Server 拿資料,否則我們的網頁會呈現一陳不變,它到變成化石(?)都只會是同一筆資料。

那麼為什麼前端一定要跟後端交換資料呢?舉個例子,假如今天我們要做一個職棒賽事的網站,這個網站理所當然必須隨著賽事的變化而變動,假如我們今天不從 Server 獲取資料,你喜歡的棒球隊如果一開場是 0,就會永遠的是 0 了 ( 喔不 ),因為資料會靜止不動,所以這也是為什麼我們必須與 Server 不斷交換資料的緣故。

而賽事的資料哪裡來?這個應該大家都很清楚,當然是中華職棒給的數據資料;那我們怎麼拿到這些資料?麥當勞服務員會送來給我們 ( 喂!!! )。

好啦,不鬧,我們可以透過中華職棒的 API 獲取資料,不知道大家還記不記得上一篇的麥當勞服務員?關於 API 如果想了解也可以去稍微看兩眼,這裡我就不再解釋 API 了。


Request 與 Response

在討論 AJAX 之前,我決定先討論 request 和 response,以免先討論 AJAX 的時候會提了一大堆的 request 和 response。

一般來說傳輸資料的兩端會分為「客戶端 ( Client )」和 「伺服器端 ( Server )」。

  • 客戶端 ( Client ):自己的瀏覽器、電腦,主要會發送「request ( 請求 )」到伺服器端 ( Server )端。
  • 伺服器端 ( Server ):收到 request 會開始處理資料,並回傳 「response ( 回應 )」到客戶端 ( Client )。

從上面的理論可以知道,網頁所呈現的圖片、資料,其實就是一大堆的 request 和 response 不斷來回傳輸。


AJAX

要再瀏覽器上面發送 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


上一篇
JavaScript Day 26. API 串接:POST、GET、DELETE、PUT/PATCH
下一篇
JavaScript Day 28. Callback Function ( 回呼函式 )
系列文
我的JavaScript日常31

尚未有邦友留言

立即登入留言