Ajax (Asynchronous JavaScript and XML) 不是新語言,而是 **瀏覽器端異步通訊技術組合** 的統稱:
本質:**單頁應用 (SPA) 與前後端分離架構的基石**。
// 1. 創建實例
const xhr = new XMLHttpRequest(); // 現代瀏覽器通用
// 2. 配置請求
xhr.open('GET', '/api/users?page=1', true); // 方法、URL、async=true
// 3. 設置請求頭 (視後端需求)
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Authorization', 'Bearer ' + token);
// 4. 註冊回調
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) { // DONE
if (xhr.status >= 200 && xhr.status < 300) {
const response = JSON.parse(xhr.responseText);
renderUserList(response.data);
} else {
showError('請求失敗: ' + xhr.status);
}
}
};
// 5. 發送
xhr.send(); // POST 時 send(body)
| readyState | 常數 | 含義 |
|---|---|---|
| 0 | UNSENT | open() 未調用 |
| 1 | OPENED | open() 已調用 |
| 2 | HEADERS_RECEIVED | 響應頭已收到 |
| 3 | LOADING | 響應體下載中 |
| 4 | DONE | 完成 (成功/失敗/中止) |
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping
public PageResult list(@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int size) {
// 查詢資料庫、封裝分頁結果
return userService.page(page, size);
}
}
// 產出 JSON: {"code":200,"data":{"records":[...],"total":100,"page":1,"size":10}}
**Fetch** 基於 Promise,語法更簡潔、支援 Stream、Service Worker、CORS 更完善,是現代 Web 標準:
async function fetchUsers(page = 1) {
try {
const response = await fetch(`/api/users?page=${page}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + getToken()
},
credentials: 'include' // 攜帶 Cookie
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const result = await response.json();
renderUserList(result.data);
} catch (err) {
showError(err.message);
}
}
const form = document.getElementById('userForm');
form.addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(form); // 自動收集 input/select/textarea
// 檔案上傳無需手動設置 Content-Type,瀏覽器自動生成 multipart/form-data; boundary=...
const res = await fetch('/api/users', { method: 'POST', body: formData });
// ...
});
const controller = new AbortController();
const signal = controller.signal;
fetch('/api/slow', { signal });
// 5 秒後取消
setTimeout(() => controller.abort(), 5000);
xhr.upload.onprogress = (e) => {
if (e.lengthComputable) {
const percent = (e.loaded / e.total * 100).toFixed(1);
progressBar.style.width = percent + '%';
}
};
OPTIONS。Access-Control-Allow-Origin (具體域名或 *)、Allow-Methods、Allow-Headers、Max-Age、Allow-Credentials (需與前端 credentials: 'include' 配合)。@JsonIgnore / @JsonBackReference 或用 DTO/VO 隔離。charset=UTF-8、後端 produces = "application/json;charset=UTF-8"、Tomcat URIEncoding=UTF-8、資料庫連接 characterEncoding=utf8。AbortController / xhr.abort())、清理事件監聽。Vue/React 用 onUnmounted/useEffect cleanup。