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


<<:  Day21 用python写UI-聊聊PanedWindow & Notebook

>>:  Vue.js 从零开始:Slot

[Day12]Die Game

上一篇介绍了Bangla Numbers,由於数字太大,所以选择使用了BigInteger,但各位也...

JavaScript Day22 - setTimeout、setInterval

setTimeout setTimeout:定时器,只执行一次,属於非同步,因此就算设定 0 秒执行...

Day22 - 铁人付外挂实作付款类别(ㄧ)- WooCommerce 金流介绍

WooCommerce 的金流主要分为两种,即时与非即时完成付款,即时指的是当订单成立後就可以取得消...

D7 - 如何用 Google Apps Script 将 Google 表单的回应即时同步在多个行事历上?

来到了第七天。老样子,先讲推荐的速解,如果你很急着用,这些 Add-On 可以帮上忙,第一是 For...