嗨,我是Hogan
目前在經營自己的自媒體 hogan.tech
主要分享一些有關於程式碼、軟體和科技業經驗分享
有興趣的讀者可以進一步關注我,進而獲得更多資訊唷!
未來文章一併更新於此網站 Hogan.B Lab
並且包含多語系 繁體中文、英文、日文、簡體中文
觀看分類:React 白話文運動、其他系列
如果想要快速查找其他文章請點選目錄
成立 hogan.tech 的初衷是
希望每個正在這條路上探索的人,
都可以透過 Hogan.tech 嘗試進入程式領域。
前一篇ES6介紹了
這邊則會專注講解非同步的JavaScript
非同步在開發中是不可或缺的概念,在之前的程式碼中目前都是同步的(Synchronous)概念,指的是說程式會依序執行。
然而在開發一個網頁的過程中,有時候需要執行非同步的(Asynchronous)的動作,例如:使用者按下表單送出,必須要等待資料傳送完畢後,獲得伺服器端回傳的資料,才能知道是否成功。
如果在伺服器回傳結果前,就直接透過JavaScript執行畫面成功與否,反而會是錯誤的。
而現代JavaScript中也有一些語法專門處理非同步的執行,包含接下來介紹的 Promise 以及Async & Await。
一個非同步的請求(request)通常有兩種結果,成功與失敗,不過實際上會有三種狀態,分別為完成(Fulfilled)、失敗(Rejected)以及等待中(Pending)。透過Promise物件,可以讓我們清楚執行了一個非同步的請求當前的狀態。
在沒有fetch函數之前,要獲得一個API資料是相當麻煩的,可能需要寫超過二十行以上的程式碼,然而ECMA為了使其更加方便,新增了fetch語法,只要短短一、兩行就可以完成「獲取API」資料。
直接用一個api實例來做舉例,這邊網路上找了一個免費的api
https://api.thecatapi.com/v1/images/search
讀者如果直接輸入於瀏覽器中,可以看到一個回傳的物件,裡面包含了id、url、width、height
那要如何使用程式碼,獲得api資料呢?
fetch("https://api.thecatapi.com/v1/images/search")
.then(res=>res.json)
.then(console.log)
.catch(console.error)
這邊只要使用fetch函數,並且將網址當作引數(argument)傳入,透過then或是catch函數可以依序的執行接下來想要執行的程式。
以上述程式碼來說,先打了一隻api,透過第一個then函數獲得回傳結果,透過第二個then函數印出訊息。最後透過catch函數,如果失敗則會印出失敗訊息。
另一個更常見也更泛用的非同步語法是使用Async & Await非同步函式(Async Function),比起Promise & Fetch,Async & Await的語法更簡潔易懂,也比較符合我們的閱讀習慣。
如果以上面的fetch then改寫成async & await 語法
const getCatData = async() => {
let res = await fetch("https://api.thecatapi.com/v1/images/search")
let { results } = await res.json()
console.log(results)
}
getCatData()
/*
[
{
id: "ac5",
url: "https://cdn2.thecatapi.com/images/ac5.jpg",
width: 565,
height: 551
}
]
*/
在函式中的第一行使用async關鍵字,告知電腦此為一個非同步函式,接下來只要在任何需要等待的非同步請求前面加上await關鍵字,即可完成此非同步函式。
那麼我們要如何獲得失敗訊息呢?
我們只要在async & await 中,再加上try & catch 語法,即可先執行try裡面的程式,並且在catch中處理Promise失敗的狀態
const getCatData = async() => {
try {
let res = await fetch("https://api.thecatapi.com/v1/images/search")
let { results } = await res.json()
console.log(results)
} catch (error) {
console.log(error)
}
}
getCatData()
上面已有提到Promise 總共有三種狀態,分別為完成(Fulfilled)、失敗(Rejected)以及等待中(Pending),不過以結果來說,最終都可以歸納為兩種結果,成功與失敗。
因此在執行一個非同步函式,也可以將執行結果回傳,並且使用Promise物件去做儲存
const getCatData = () =>
new Promise((resolves, rejects) => {
const api = "https://api.thecatapi.com/v1/images/search"
const request = new XMLHttpRequest;
request.open("GET", api);
request.onload = () => {
request.status === 200 ?
resolves(JSON.parse(request.response).results) :
rejects(Error(request.statusText))
}
request.onerror = err => rejects(err);
request.send()
})
這篇講解了,非同步(Asynchronous)的概念以及一些實作,不過非同步本身是一個比較困難的概念,且其中的一些語法都是有點難度的,也歡迎讀者收藏此文章,未來都可以回過頭來複習此內容。
如果有任何建議與疑問也歡迎留言!
如果喜歡此系列文章,請不吝於按下喜歡及分享,讓更多人看到唷~