因為昨天文章發的有點匆忙,
今天的文章會再補充一下昨天介紹的 XHR,
然後練習 fetch 的用法~
昨天練習了用 XHR 拿資料的方法,
但是有沒有覺得它用起來有點麻煩?
前面都要先宣告 XMLHttpRequest 的物件,
然後還得寫 open 跟 send 才會真的發送請求出去:
const xhr = new XMLHttpRequest();
xhr.open("get", sourceUrl, true);
xhr.send(null);
再來好不容易發送請求出去了,
你還沒辦法直接取用 call API 後回傳的資料,
還得再多寫 xhr.onload
,
這時候才拿得到資料才能做後續的處理:
xhr.onload = function () {
setdataResult(JSON.parse(xhr.responseText));
};
}
而且如果是直接在 xhr.onload
裡面寫變數,
因為是在 function 內,
function 外沒辦法直接取得這個變數(作用域的關係),
例如這邊將昨天的例子改寫成這樣:
function fetchData(){
const xhr = new XMLHttpRequest();
xhr.open("get", sourceUrl, true);
xhr.send(null);
xhr.onload = function () {
result = JSON.parse(xhr.responseText);
console.log(result);
};
console.log(result);
}
然後文字的地方改成直接取用 {result}
<Text my={4} fontSize="p" textAlign="center">
result: {result?.records?.location?.length}
</Text>
這樣在 xhr.onload
外面其實是拿不到資料的(要另外處理),
所以昨天後來我是用 useState
去改值(將拿到的資料設定進去),
這樣是不是有夠麻煩orz
因為 XMLHttpRequest 算是很陽春的 AJAX 實作方法,
所以之後也出現了幾個好用的工具,
我覺得應該是為了克服 XHR 的一些缺點啦。
像是今天要練習的 fetch
就是其中一個,
而 fetch
是使用 Promise
物件的寫法,
那 Promise
又是什麼呢?
Promise
要認真說的話又可以獨立一篇了XD
這邊推薦可以看大大的文章 → JavaScript Promise 全介紹
我自己簡單的理解就是,Promise
是為了優化 Javascript 的 非同步
語法部份,
例如在寫 Javascript 時你會發現你寫在前後行的語法(EX: 執行A; 執行B;
),
但並不會真的照你寫的順序執行,
而是"同時"執行,
所以如果你需要寫 A執行完才要執行B 的語法,Promise
就能解決這個問題~
前情提要講完了,
那我們接下來就看一下 fetch 的簡單寫法吧:
function fetchData(){
fetch(sourceUrl)
.then(function(response) {
return response.json();
})
.then(function(myJson) {
console.log(myJson);
});
}
簡單說明一下,fetch(sourceUrl)
這邊意思就是傳送要求到 sourceUrl
,
等到拿到 response 之後(.then) 回傳 response.json()
,
接著(.then) 再用 console.log 把 response.json()
印出來,
像這樣:
不需要特別寫 open
, send
, onload
就能完成 call API 並拿到回傳資料,
這樣是不是簡單多了呢?
既然 fetch 拿資料這麼方便,
那我們今天用拿到的資料來簡單寫一下應用好了。
首先在動手前,昨天也有提到我會習慣先觀察一下資料:
https://opendata.cwb.gov.tw/api/v1/rest/datastore/F-C0032-001?Authorization=rdec-key-123-45678-011121314
題外話,你可能會發現資料長得很密密麻麻要怎麼看?
這邊推薦可以裝 Chrome 的擴充套件 JSON Viewer,
然後它就會把 JSON 轉換成比較可讀的樣子,
像這樣:
從資料裡面可以看到有各縣市的明日天氣預報資料,
現在假設我明天要去臺中玩(並沒有T_T),
我想關心一下臺中明天的天氣情況,
這邊就稍微處理一下拿到的資料,
我習慣是觀察好資料結構後,先拿一筆資料試寫看看(這邊容我這邊快轉一下):
function App() {
const sourceUrl =
"https://opendata.cwb.gov.tw/api/v1/rest/datastore/F-C0032-001?Authorization=rdec-key-123-45678-011121314";
const [dataResult, setdataResult] = useState([]);
const searchArea = '臺中市';
const [dataSearchArea, setDataSearchArea] = useState({});
let result = [];
function fetchData(){
fetch(sourceUrl)
.then(function(response) {
return response.json();
})
.then(function(myJson) {
setdataResult(myJson.records.location);
});
}
useEffect(() => {
setDataSearchArea(dataResult.filter((d) => d.locationName === searchArea));
}, [dataResult]);
return (
<ChakraProvider theme={theme}>
<>
<Text my={4} fontSize="p" textAlign="center">
sourceUrl: {sourceUrl}
</Text>
<Text my={4} as="h2" fontSize="2xl" textAlign="center">
全部總共 {dataResult.length === 0 ? 0 : dataResult?.length } 筆資料
</Text>
<Divider my={4} />
<Text my={4} as="h3" fontSize="xl" textAlign="center">
區域: {searchArea}
</Text>
<Text px={4}>
[明日天氣預報]
<br />
時間:{dataSearchArea[0]?.weatherElement[0]?.time[0]?.startTime}
{' ~ '}
{dataSearchArea[0]?.weatherElement[0]?.time[0]?.endTime}
<br />
天氣:{dataSearchArea[0]?.weatherElement[0]?.time[0]?.parameter?.parameterName}
</Text>
<Divider my={4} />
<Center>
<Button onClick={fetchData}>取得資料</Button>
</Center>
</>
</ChakraProvider>
);
}
然後從資料我們可以看到每天的預報資料有 3 筆 (在 time
裡面),
所以先用一筆確定是你要的畫面之後,
我就會把 time
用 map
以迴圈的方式讀取,把 3 筆資料都渲染出來,
像這樣:
taSearchArea[0]?.weatherElement[0]?.time?.map((t) => (
<Box>
時間:{t.startTime}
{' ~ '}
{t.endTime}
<br />
天氣:{t.parameter?.parameterName}
</Box>
))}
這樣你就可以看到臺中市的明天天氣預報資料都出現了~(看起來不會下雨真是太好了但我不會去臺中玩QQ)
到這邊千萬不要高興太早,
如果你去 fetch 遇到 error (EX. 目的地server掛掉,或網址打錯...等)
那會怎樣呢?
這邊我故意把 url 多打字來試試看:
你可以看到畫面上都沒有資料,
打開 console 來看可以看到有 error
(PS. 其實一般來說,應該是瀏覽器會直接跳 error 畫面,
所以 error 是需要另外處理的,
但可能我裝的套件有特別處理這個事件,所以畫面上很安靜什麼都沒發生)
這種情況該怎麼辦呢?Promise
有提供 catch
的語法,
讓你設定在執行前面動作遇到 error 會執行什麼動作,
像這樣:
fetch(sourceUrl)
.then(function(response) {
return response.json();
})
.then(function(myJson) {
setdataResult(myJson.records.location);
})
.catch((err) => {
alert("抓取資料錯誤,請確認後再試");
console.log(err);
})
這邊你就會看到跳出一個警告視窗顯示:抓取資料錯誤,請確認後再試,
而這個就是 Exception Handling(例外處理)
,
顧名思義,就是在程式未正常執行時要做什麼處理,
尤其是在跟後端介接 call API 時,例外處理就會變得很重要,
要依據後端給出的 error code 不同時要做不同的處理,
像是前端顯示不同的錯誤訊息,
讓使用者或工程師看到很快知道要怎麼處理這樣~
因此後面的篇章 catch
會常常出現,
也是我們在 call 後端 API 時一定要寫的語法,
今天介紹完 fetch
明天就讓我們進入 axios
的世界吧~~~
request的方式? ajax & fetch & axios
今天終於比較沒那麼趕了orz
感覺好像每年中秋連假都在寫鐵人賽文章中度過XD
真充實XDDDD