在網頁發展史之中,人們對於網頁的需求不再是單純的 靜態網頁
,人們追求可變化的網頁內容,透過後台設定資料進行渲染不同的內容,這樣的需求漸漸的深耕於人們心中, 動態網頁
概念隨即而生。
這想法是指網頁不再像靜態網頁一般,而是透過 Client 與 Server 相互呼應來渲染網頁,在剛開始有動態網頁的需求時,前輩們透過 form 表單與 Server 端進行溝通,以抓取相應區塊所需要的資料來進行渲染,隨著網路頁面雨後春筍般的冒出來之後,使用者體驗這概念也被大眾們認同與接受後,網頁供應商面來的其中幾個問題之一,如何讓使用者不會看到出現空白頁的情況。
這其中有一個很重要的技術來解決了這問題而他就是今天的主角,也就是 AJAX(Asynchronous JavaScript and XML)
,透過 JS 進行非同步的抓取資料,來避免使用者體驗不舒服的部分,而延伸出了下列幾種方式來提供前端人員使用。
不管是何種方式只要記住溝通方式不變的定理
Client send Request to Server
- 發送特定通道與請求內容給予 Server,Server Response something to Client
- Server 透過請求內容回覆相應的資料實體。下列會依序介紹上方提到的那幾種溝通方式。
W3C 標準的非同步請求。JS 原生方法不用額外安裝其他套件。
const xhr = new XMLHttpRequest()
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");
xhr.send(payload)
payload {string} 當 method 為 POST 時採參數可以當作傳送的訊息,若為 GET 必須給予 null。
//- e.g.
xhr.send("name=test001&account=test001")
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))
}
})
})
}
JQuery 函數庫提供,與 XMLHttpRequest 使用上差異在於 JQuery 已將 ajax 包裝過後,可方便使用。
答案是: 不行!但是他非常的便利(誤)。
JQuery
是由 JS 組成的函式庫,建立於 2006 年,在前端領域橫行了數餘年,曾經的霸主,函式庫內容包含了 DOM 操作、動畫、監聽事件等,讓前端開發人員在開發時睡覺會笑出來,因為有了它感覺錢都是從天上掉下來了,於是他有另外一個簡稱 $
(我是亂說的)。
而 JQuery 提供的 Ajax
function,是由原生的 XMLHttpRequest 進行開發,改善了原本在使用上的不方便。
非同步模式
時可以透過 Promise
(此模式只有在 v1.5 之後採可以使用) 代替 XMLHttpRequest 監聽事件,透過 done/fail/done 來精準表達現行請求正在哪個階段。下方就來介紹他吧!
<script src="https://code.jquery.com/jquery-3.4.1.js"
integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU="crossorigin="anonymous"></script>
//- 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 ,但若這樣那我們每次都會引用一個好大好大的包,但只用一小部分,而這就是他的缺點!
Fetch API 提供了一種 JavaScript Interface 來操作 HTTP pipeline,比方 request 和 response。同時它也提供了 global 的 fetch() (en-US) method,使得在網路上非同步地 fetch resources 這件事變得簡單易懂。 - 取自 MDN
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 等三個階段進行資料的處理。
這裡有需要特別注意的地方,因為fetch 回傳資料是 ReadableStream 類別,必須透過相應的解析 blob(), json(), text()
等方式來獲取資訊。 想深入了解可以 點選這裡 。
但美好的事物總是會有一點點的缺漏, fetch 也無法逃過,就算 http code 回傳失敗時,他也會變成 reslove
XMLHttpRequest - Web APIs | MDN
jQuery.ajax() | jQuery API Documentation
Fetch API - Web APIs | MDN