iT邦幫忙

0

[穩扎穩打系列] AJAX 請求大補帖

  • 分享至 

  • xImage
  •  

前言

在網頁發展史之中,人們對於網頁的需求不再是單純的 靜態網頁,人們追求可變化的網頁內容,透過後台設定資料進行渲染不同的內容,這樣的需求漸漸的深耕於人們心中, 動態網頁 概念隨即而生。

這想法是指網頁不再像靜態網頁一般,而是透過 Client 與 Server 相互呼應來渲染網頁,在剛開始有動態網頁的需求時,前輩們透過 form 表單與 Server 端進行溝通,以抓取相應區塊所需要的資料來進行渲染,隨著網路頁面雨後春筍般的冒出來之後,使用者體驗這概念也被大眾們認同與接受後,網頁供應商面來的其中幾個問題之一,如何讓使用者不會看到出現空白頁的情況。

這其中有一個很重要的技術來解決了這問題而他就是今天的主角,也就是 AJAX(Asynchronous JavaScript and XML),透過 JS 進行非同步的抓取資料,來避免使用者體驗不舒服的部分,而延伸出了下列幾種方式來提供前端人員使用。

  1. XMLHttpRequest
  2. JQuery Ajax
  3. fetch API
  4. axios

不管是何種方式只要記住溝通方式不變的定理

  1. Client send Request to Server - 發送特定通道與請求內容給予 Server,
  2. Server Response something to Client - Server 透過請求內容回覆相應的資料實體。

小朋友點點名

下列會依序介紹上方提到的那幾種溝通方式。

1. XMLHttpRequest

W3C 標準的非同步請求。JS 原生方法不用額外安裝其他套件。

建立處理變數 xhr
const xhr = new XMLHttpRequest()
建立 request 實體 xhr.open(method,url,async)

method {string} 為 GET, POST, PUT, PUCH
url {string} API 溝通位址
async {boolean} 是否開啟非同步模式

//- e.g. method use get
xhr.open('get','https://something-domain.com',true)
//- e.g. method use post
xhr.open('post','https://something-domain.com',true)
//- 插入 RequestHeader 可額外設定 ApiToken 等 Header
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
送出 request 實體 xhr.send(payload)

payload {string} 當 method 為 POST 時採參數可以當作傳送的訊息,若為 GET 必須給予 null。

//- e.g.
xhr.send("name=test001&account=test001")
等待 xhr 回應,監聽 readState 狀態以確保該請求已完成

0: 還沒開始
1: 讀取中
2: 已讀取
3: 資訊交換中
4: 完成

xhr.onreadystatechange = function () {
    if (this.readyState === 4 && this.status === 200) {
       //- 當請求完成並且成功時 ...
    }
};

xhr.onload(()=>{
  //- 當請求 onload 時 ...
})
xhr.onerror(()=>{
  //- 當請求 error 時 ...
})

OK 我們已經將 XMLHttpRequest 建立與發送相關訊息已經完成摟!,可見我們在流程上,先是建立在進行相關設定(Header、Method等),才能透過 send function 進行送出,並且透過 Object Class 來呼叫對應 function 來執行相應的動作,並且需要透過監聽的方式來處理,判斷是否還有呼吸,雖然流程上很明確但是卻顯得很攏長並且過程也是相當的繁瑣。

加碼放送透過 Promise 來封裝 XMLHttpRequest

//- 當 res status === 200 都當作是正確
//- 當 res status !== 200 都當作是錯誤 reject
const get = (url) => {
  return new Promise((resolve, reject) => {
    const req = new XMLHttpRequest()
    req.open('GET', url)
    req.send()

    req.onload(() => {
      if (req.status === 200) {
        resolve(req.response) // 這邊 req.responese 是 JSON 可以先進行 JSON.parse
      } else {
        reject(new Error(req))
      }
    })
  })
}

2. JQuery Ajax

JQuery 函數庫提供,與 XMLHttpRequest 使用上差異在於 JQuery 已將 ajax 包裝過後,可方便使用。

JQuery 是什麼可以吃嗎?

答案是: 不行!但是他非常的便利(誤)。

JQuery 是由 JS 組成的函式庫,建立於 2006 年,在前端領域橫行了數餘年,曾經的霸主,函式庫內容包含了 DOM 操作、動畫、監聽事件等,讓前端開發人員在開發時睡覺會笑出來,因為有了它感覺錢都是從天上掉下來了,於是他有另外一個簡稱 $ (我是亂說的)。

而 JQuery 提供的 Ajax function,是由原生的 XMLHttpRequest 進行開發,改善了原本在使用上的不方便。

  1. XMLHttpRequest 難以確認各階段的狀態
  2. XMLHttpRequest 在寫法上的攏長,往往一個請求要寫的漏漏長。
    最精彩的莫過於此請求開啟非同步模式時可以透過 Promise(此模式只有在 v1.5 之後採可以使用) 代替 XMLHttpRequest 監聽事件,透過 done/fail/done 來精準表達現行請求正在哪個階段。

下方就來介紹他吧!

安裝 JQuery CDN
<script src="https://code.jquery.com/jquery-3.4.1.js"
integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU="crossorigin="anonymous"></script>
使用方式 $.ajax(config)
//- config 由下列 Key 組成,此篇章只抓取部分常用來說明。
{
    type, //- {string} 為 GET, POST, PUT, PUCH
    url,  //- {string}  Server API 溝通位址
    dataType,  //- {string} Server 傳回的資料類型
    timeout,  //- {number} 請求抓取時間當超過時會中斷溝通
    data,  //- {object} 傳輸給 Server 夾帶資料
    async,  //- {boolean} 是否開啟非同步模式
    success, //- {function} 當 API 成功時需要做什麼
    error,  //- {function} 當 API 失敗時需要做什麼
}
//- ...

一般使用方式

$.ajax{
    type,
    url,
    dataType,
    timeout,
    async,
    success: function (){
        //- todo success
    },
    error: function(){
        //- todo error
    },
}

透過 Promise 來完成

$.ajax(config)
  .done(()=>{
      //- todo success 
  })
  .fail(()=>{
      //- todo error
  })
  
//- or
$.ajax(config)
  .then(()=>{
      //- todo success 
  }, ()=>{
      //- todo error
  })

是不是非常的完美啊!但你有發現一個問題嗎~好像每次我只要用到 JQuery Ajax 時就必須將所有的, JQuery 進行 CDN ,但若這樣那我們每次都會引用一個好大好大的包,但只用一小部分,而這就是他的缺點!

3. fetch API

Fetch API 提供了一種 JavaScript Interface 來操作 HTTP pipeline,比方 request 和 response。同時它也提供了 global 的 fetch() (en-US) method,使得在網路上非同步地 fetch resources 這件事變得簡單易懂。 - 取自 MDN

使用方式 fetch

Method GET :

fetch('http://something-domain.com/get/heee')
  .then(function(response) {
    return response.json();
  })
  .then(function(myJson) {
    console.log(myJson);
  }); 

由上方案例可以看到,fetch 是回傳 Promise,所以在使用上可以透過 then / catch / finally 等三個階段進行資料的處理。

  • then 獲取成功下一步。
  • catch 失敗了! 請做相應處理。
  • finally 完成上述所有步驟。

這裡有需要特別注意的地方,因為fetch 回傳資料是 ReadableStream 類別,必須透過相應的解析 blob(), json(), text() 等方式來獲取資訊。 想深入了解可以 點選這裡

但美好的事物總是會有一點點的缺漏, fetch 也無法逃過,就算 http code 回傳失敗時,他也會變成 reslove

4. axios 可直接觀看下一篇章

引用

XMLHttpRequest - Web APIs | MDN
jQuery.ajax() | jQuery API Documentation
Fetch API - Web APIs | MDN


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言