# JSON
根據維基百科的敘述它是一個輕量的資料交換語言,且是獨立於語言的文字格式。
# AJAX
Ajax(非同步傳輸),只更新網頁的一部份,畫面不會整個刷新,傳統的方法是建立 XMLHttpRequest 物件
const xhr = new XMLHttpRequest(); //建立XMLHttpRequest物件,藉由此物件控制跟伺服器通訊的部分
//get表示讀取資料,後面的url是要讀取的網址,這邊的API使用opendata的展覽資訊作示範
//true(非同步):不會等資料回傳就往下繼續執行,false(同步):等資料回傳才繼續執行
xhr.open(
'get',
'https://cloud.culture.tw/frontsite/trans/SearchShowAction.do?method=doFindTypeJ&category=6',
true
);
xhr.send(null); //因為我們只要get資料,所以傳送空值(null)
xhr.onload = function () {
//onload為資料載入完成時,才執行function
const str = JSON.parse(xhr.responseText); //把JSON變為物件,另外JSON.stringify()是把物件變為JSON
const main = document.querySelector('.culture');
let str2 = ''; //建一個空字串
for (let i = 0; i < 100; i++) {
//跑for迴圈,塞入組好的字串,把100筆主題顯示出來
str2 += `<li>主題: ${str[i].title}</li>`;
}
main.innerHTML = str2; //寫入
};
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div class="content">
<ul class="culture"></ul>
</div>
<script src="/test18.js"></script>
</body>
</html>
結果(100 筆)
在瀏覽器的 console 輸入 xhr,可看到一些資訊
readyState
- 0- 還沒連接你所撈的資料
- 1- open()被呼叫,但還沒有把資料傳送過去
- 2- send()被呼叫
- 3- 資料下載中,此時 responseText 有部分資料
- 4- 已完全接收到資料
status
- 200-資料正確回傳
- 404-資料讀取錯誤
- 其他狀態碼可至MDN (opens new window)查看
WARNING
缺點:寫法複雜,會有回呼地獄(Callback Hell)的問題
# 使用其他框架來非同步傳輸
# jQuery 的 ajax()
//記得HTML要引入jQuery
// 例如:<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
$(document).ready(() => {
$.ajax({
url:
'https://cloud.culture.tw/frontsite/trans/SearchShowAction.do?method=doFindTypeJ&category=6',
type: 'GET', //請求的方式,這邊使用GET來拿資料
dataType: 'json', //返回的資料類型
//成功時呼叫這個callback
success: res => {
console.log(res);
},
//失敗時呼叫這個callback
error: err => {
console.log(err);
}
});
});
其他參數可到W3Schools (opens new window)查看
缺點:單純使用ajax卻要引入整個jQuery
# Fetch
const url = `https://cloud.culture.tw/frontsite/trans/SearchShowAction.do?method=doFindTypeJ&category=6`;
fetch(url, {method:'GET'})//預設已經為GET
.then((res) => {
console.log(res.json());//輸出成 json
}).catch((err) =>{
console.log(err);
});
缺點:瀏覽器支援度低、不會帶cookie、404、500都會當作成功的請求
# Axios
//Axios-CDN:https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js
axios({
method: 'get',
url: 'https://cloud.culture.tw/frontsite/trans/SearchShowAction.do?method=doFindTypeJ&category=6',
})
.then((res) => {
console.log(res)
})
.catch((err) => {
console.log(err)
});
目前最為推薦的方法,防XSRF(CSRF) (opens new window)、輕量、支持Promise API
# Promise
它是一個語法,用來處理非同步行為,並使用Async、Await讓結構看起來像同步語言,基本的結構如下圖
# Promise基礎概念
function prFn(num) {//沒有回傳結果時,會是pending的狀態
//要傳入function作為參數,且此function參數分別代表成功與失敗時所回傳的結果
return new Promise((resolve, reject) => {
num ? resolve('成功') : reject('失敗')
});
}
prFn(1)//執行prFn並把參數代入
.then((res) => {//接收成功時所回傳的結果(但它其實也可以傳入失敗的結果 但必須再塞入一個callback function)
console.log(res);
console.dir(Promise);//Promise原型方法有catch、finally、then
})
.catch((err) => {//接收失敗時所回傳的結果
console.log(err);
});
# Promise鏈接技巧
function prFn(num) {
return new Promise((resolve, reject) => {
num ? resolve('成功') : reject('失敗')
});
}
prFn(0)
.then((res) =>{
console.log(` 1: ${res} `);
}, (rej) => {
console.log(` 1(err): ${rej} `);//前面所提到的,then也可以拿來接收失敗時回傳的結果
return prFn(2);//return的結果,透過下一個then接收,就可以一直串接
}).then((res) => {
console.log(` 2: ${res} `);
})
.catch((err) => {
console.log(err);
});
# Promise.all() & Promise.race()
//Promise.all()
function prFn(num, time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if(num){
resolve(`成功 ${num}`)
}else{
reject('失敗');
}
}, time);
});
}
Promise.all([//同時發出請求,不管誰先誰後,其中一個為reject狀態就會進catch
prFn(1),
prFn(2),
prFn(3),
prFn(4),
prFn(5),
])
.then((res) => {
console.log(res);
})
.catch((res) => {
console.log(res);
});
//Promise.race()
function prFn(num, time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if(num){
resolve(`成功 ${num}`)
}else{
reject('失敗');
}
}, time);
});
}
Promise.race([//只會回傳第一個完成的結果,且在第一個被拒絕的情況下才會進入catch
prFn(1, 500),
prFn(0,1000),
prFn(3,1500),
prFn(4,3000),
prFn(5,3500),
])
.then((res) => {
console.log(res);
})
.catch((res) => {
console.log(res);
});
# Async & Await
- 基於Promise實現
- 避免鏈式調用Promise
function prFn(num,time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if(num){
resolve(`成功 ${num}`)
}else{
reject('失敗');
}
}, time);
});
}
//使用async await簡化.then() & .catch()取得回傳結果的過程
async function getOpendata() {
const result = await Promise.all([prFn(1, 500),prFn(2, 1000),prFn(3, 2000)]);
console.log(result);
}
getOpendata();
(async () => {//使用IIFE & try catch捕捉error
try{
const { data } = await axios.get('https://cloud.culture.tw/frontsite/trans/SearchShowAction.do?method=doFindTypeJ&category=6');
console.log(data);
}catch (err) {
throw new Error(err);
}
})();
參考文獻:
JavaScript 核心篇 (opens new window)
RocMark-axios 介紹 (opens new window)
程式前沿-通過一些例子深入瞭解JavaScript的Async和Await (opens new window)
Wang Casper 鐵人賽:JavaScript Await 與 Async (opens new window)
Noob's Space-我要學會 JS(三):callback、Promise 和 async/await 那些事兒 (opens new window)