首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Ajax 技術原理與實戰:從 XMLHttpRequest 到 Fetch API 的演進

     編輯:Java 相關知識

什麼是 Ajax?

Ajax (Asynchronous JavaScript and XML) 不是新語言,而是 **瀏覽器端異步通訊技術組合** 的統稱:

  • 異步:不阻塞主執行緒,發送請求後繼續響應用戶操作,回調處理響應。
  • JavaScript:客戶端腳本語言,操作 DOM、發起請求、處理回調。
  • XMLHttpRequest (XHR):核心 API 物件,支援 HTTP 請求/響應、多種資料格式 (不限 XML,JSON/HTML/Blob 皆可)。
  • DOM:動態更新頁面局部,無需整頁重載。

本質:**單頁應用 (SPA) 與前後端分離架構的基石**。

XHR 核心流程詳解

// 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常數含義
0UNSENTopen() 未調用
1OPENEDopen() 已調用
2HEADERS_RECEIVED響應頭已收到
3LOADING響應體下載中
4DONE完成 (成功/失敗/中止)

服務端配合:Spring MVC 範例

@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 API

**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);
    }
}

進階實戰模式

1. 表單提交 (FormData)

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 });
    // ...
});

2. 取消請求

const controller = new AbortController();
const signal = controller.signal;
fetch('/api/slow', { signal });
// 5 秒後取消
setTimeout(() => controller.abort(), 5000);

3. 進度條 (上傳/下載)

xhr.upload.onprogress = (e) => {
    if (e.lengthComputable) {
        const percent = (e.loaded / e.total * 100).toFixed(1);
        progressBar.style.width = percent + '%';
    }
};

4. 跨域 (CORS) 核心原理

  • 瀏覽器同源策略限制 JS 跨域讀取響應。
  • 非簡單請求 (自定義 Header、非 GET/POST/HEAD、Content-Type 非表單類型) → **預檢請求** 發送 OPTIONS。
  • 後端需回應:Access-Control-Allow-Origin (具體域名或 *)、Allow-Methods、Allow-Headers、Max-Age、Allow-Credentials (需與前端 credentials: 'include' 配合)。

常見坑與最佳實踐

  1. 迴圈引用序列化爆炸:實體類加 @JsonIgnore / @JsonBackReference 或用 DTO/VO 隔離。
  2. 中文亂碼:前端 charset=UTF-8、後端 produces = "application/json;charset=UTF-8"、Tomcat URIEncoding=UTF-8、資料庫連接 characterEncoding=utf8。
  3. 重複提交:按鈕 loading 狀態禁用、冪等 Token (Redis SETNX)、後端幂等性設計。
  4. 記憶體洩漏:組件銷毀時取消進行中請求 (AbortController / xhr.abort())、清理事件監聽。Vue/React 用 onUnmounted/useEffect cleanup。
  5. 安全:CSRF Token (雙重 Cookie/Header)、XSS 防護 (輸出編碼、CSP)、SQL 注入 (參數化查詢)。

生態工具推薦

  • Axios:Promise 封裝、攔截器、自動轉 JSON、取消、進度、TypeScript 一級支援,**企業級首選**。
  • SWR / React Query / TanStack Query:資料獲取、快取、重試、去重、分頁、樂觀更新,**React/Vue/Svelte 現代資料層標配**。
  • OpenAPI Generator:從 Swagger 文檔自動生成 TypeScript/Java/Kotlin 客戶端代碼,端到端類型安全。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved