【Web API系列】XMLHttpRequest API和Fetch API深入理解與應用指南

在這里插入圖片描述


前言

在現代Web開發中,客戶端與服務器之間的異步通信是構建動態應用的核心能力。無論是傳統的AJAX技術(基于XMLHttpRequest)還是現代的Fetch API,它們都為實現這一目標提供了關鍵支持。本文將從底層原理、核心功能、代碼實踐到實際應用場景,系統性地對比和分析這兩種API的異同,幫助你掌握如何在不同場景下選擇最佳解決方案。


文章目錄

  • 前言
  • 一、XMLHttpRequest API:傳統異步請求的基石
    • 1.1 核心概念與工作原理
    • 1.2 關鍵功能與高級用法
    • 1.3 局限性分析
  • 二、Fetch API:現代Web請求的標準方案
    • 2.1 設計理念與核心優勢
    • 2.2 基礎用法與代碼示例
    • 2.3 高級功能實踐
    • 2.4 常見問題與解決方案
  • 三、XMLHttpRequest與Fetch API的深度對比
    • 3.1 功能特性對比
    • 3.2 性能與適用場景
  • 四、實戰案例:構建一個健壯的HTTP客戶端
    • 4.1 基于Fetch的封裝庫
    • 4.2 實現文件分片上傳
  • 總結


一、XMLHttpRequest API:傳統異步請求的基石

1.1 核心概念與工作原理

XMLHttpRequest(XHR)是瀏覽器提供的原生API,用于在不刷新頁面的情況下與服務器交換數據。其核心流程包括:

  1. 實例化對象:通過構造函數創建XMLHttpRequest實例。
  2. 配置請求:指定HTTP方法、URL及是否異步。
  3. 綁定事件:監聽請求狀態變化(如onloadonerror)。
  4. 發送請求:調用send()方法并處理響應數據。
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.example.com/data', true);
xhr.onload = function() {if (xhr.status === 200) {console.log(JSON.parse(xhr.responseText));} else {console.error('請求失敗:', xhr.status);}
};
xhr.onerror = function() {console.error('網絡錯誤');
};
xhr.send();

1.2 關鍵功能與高級用法

  • 同步與異步模式

    // 同步請求(阻塞主線程,不推薦)
    xhr.open('GET', 'https://api.example.com/data', false);
    xhr.send();
    console.log(xhr.responseText);
    
  • 處理二進制數據

    xhr.responseType = 'arraybuffer';
    xhr.onload = function() {const buffer = xhr.response;// 處理二進制數據(如圖像或文件)
    };
    
  • 上傳進度監控

    xhr.upload.onprogress = function(event) {const percent = (event.loaded / event.total) * 100;console.log(`上傳進度: ${percent}%`);
    };
    
  • 超時控制

    xhr.timeout = 5000; // 5秒超時
    xhr.ontimeout = function() {console.error('請求超時');
    };
    

1.3 局限性分析

  1. 回調地獄:事件監聽機制導致代碼嵌套復雜。
  2. 錯誤處理不統一:需手動檢查HTTP狀態碼和網絡錯誤。
  3. 不支持Promise:與現代異步編程模式不兼容。

二、Fetch API:現代Web請求的標準方案

2.1 設計理念與核心優勢

Fetch API基于Promise設計,提供更簡潔、靈活的請求方式,并天然支持以下特性:

  • 鏈式調用:避免回調嵌套。
  • Streams API集成:處理流式數據(如大文件下載)。
  • CORS與安全策略:默認不發送跨域Cookie,需顯式配置。

2.2 基礎用法與代碼示例

fetch('https://api.example.com/data').then(response => {if (!response.ok) throw new Error('HTTP錯誤');return response.json();}).then(data => console.log(data)).catch(error => console.error('請求失敗:', error));

2.3 高級功能實踐

  • 自定義請求頭與模式

    fetch('https://api.example.com/data', {method: 'POST',headers: {'Content-Type': 'application/json','Authorization': 'Bearer token'},body: JSON.stringify({ key: 'value' }),mode: 'cors', // 跨域模式credentials: 'include' // 包含Cookie
    });
    
  • 中斷請求(AbortController)

    const controller = new AbortController();
    setTimeout(() => controller.abort(), 5000);fetch('https://api.example.com/data', {signal: controller.signal
    }).catch(error => {if (error.name === 'AbortError') {console.log('請求被手動取消');}
    });
    
  • 流式數據處理

    fetch('https://api.example.com/large-file').then(response => {const reader = response.body.getReader();return new ReadableStream({start(controller) {function push() {reader.read().then(({ done, value }) => {if (done) {controller.close();return;}controller.enqueue(value);push();});}push();}});}).then(stream => new Response(stream)).then(response => response.blob());
    

2.4 常見問題與解決方案

  • 錯誤處理優化

    async function fetchWithRetry(url, retries = 3) {for (let i = 0; i < retries; i++) {try {const response = await fetch(url);if (!response.ok) throw new Error('HTTP錯誤');return await response.json();} catch (error) {if (i === retries - 1) throw error;await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));}}
    }
    
  • 超時封裝

    function fetchWithTimeout(url, timeout = 5000) {return Promise.race([fetch(url),new Promise((_, reject) =>setTimeout(() => reject(new Error('請求超時')), timeout))]);
    }
    

三、XMLHttpRequest與Fetch API的深度對比

3.1 功能特性對比

特性XMLHttpRequestFetch API
Promise支持
請求取消是(abort())是(AbortController)
流式數據處理有限支持完全支持
CORS處理需手動配置默認安全策略
Service Worker不支持完全集成

3.2 性能與適用場景

  • XMLHttpRequest適用場景

    • 需要監控上傳/下載進度。
    • 兼容舊版瀏覽器(如IE10及以下)。
  • Fetch API推薦場景

    • 現代Web應用開發。
    • 需要與Service Worker配合實現離線緩存。
    • 處理流式數據或大文件。

四、實戰案例:構建一個健壯的HTTP客戶端

4.1 基于Fetch的封裝庫

class HttpClient {constructor(baseURL, headers = {}) {this.baseURL = baseURL;this.headers = headers;}async request(endpoint, options = {}) {const url = `${this.baseURL}${endpoint}`;const response = await fetch(url, {...options,headers: { ...this.headers, ...options.headers }});if (!response.ok) {const error = new Error(`HTTP ${response.status}`);error.response = response;throw error;}const contentType = response.headers.get('content-type');if (contentType?.includes('application/json')) {return response.json();}return response.text();}get(endpoint, params) {const query = new URLSearchParams(params).toString();return this.request(`${endpoint}?${query}`, { method: 'GET' });}post(endpoint, body) {return this.request(endpoint, {method: 'POST',body: JSON.stringify(body),headers: { 'Content-Type': 'application/json' }});}
}// 使用示例
const api = new HttpClient('https://api.example.com', {Authorization: 'Bearer token'
});
api.get('/users', { page: 1 }).then(users => console.log(users));

4.2 實現文件分片上傳

async function uploadFile(file, chunkSize = 1024 * 1024) {const totalChunks = Math.ceil(file.size / chunkSize);for (let i = 0; i < totalChunks; i++) {const start = i * chunkSize;const end = Math.min(start + chunkSize, file.size);const chunk = file.slice(start, end);const formData = new FormData();formData.append('file', chunk);formData.append('chunkIndex', i);formData.append('totalChunks', totalChunks);await fetch('/upload', {method: 'POST',body: formData});}
}

總結

XMLHttpRequest作為Web異步通信的奠基者,至今仍在特定場景下發揮作用,而Fetch API憑借其現代化的設計正在成為主流選擇。開發者需要根據以下因素決策:

  1. 瀏覽器兼容性:如需支持舊版瀏覽器,XHR仍是必要選項。
  2. 功能需求:進度監控、請求取消等特性可能影響技術選型。
  3. 代碼可維護性:Fetch的Promise鏈與async/await語法更易維護。

未來,隨著Web Streams API和Service Worker的普及,Fetch API將在性能優化和離線體驗領域展現更大潛力。建議在新項目中優先采用Fetch,同時保持對XHR原理的理解以應對遺留系統維護需求。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/76477.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/76477.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/76477.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[特殊字符] Spring Boot 日志系統入門博客大綱(適合初學者)

一、前言 &#x1f4cc; 為什么日志在項目中如此重要&#xff1f; 在開發和維護一個后端系統時&#xff0c;日志就像程序運行時的“黑匣子”&#xff0c;幫我們記錄系統的各種行為和異常。一份良好的日志&#xff0c;不僅能幫助我們快速定位問題&#xff0c;還能在以下場景中…

IP協議之IP,ICMP協議

1.因特網中的主要協議是TCP/IP&#xff0c;Interneet協議也叫TCP/IP協議簇 2.ip地址用點分十進制表示&#xff0c;由32位的二進制表示&#xff0c;兩部分組成&#xff1a;網絡標識主機標識 3.IP地址分類; A:0.0.0.0-127.255.255.255 B&#xff1a;128.0.0.0-191.255.255.25…

GPIO_ReadInputData和GPIO_ReadInputDataBit區別

目錄 1、GPIO_ReadInputData: 2、GPIO_ReadInputDataBit: 總結 GPIO_ReadInputData 和 GPIO_ReadInputDataBit 是兩個函數&#xff0c;通常用于讀取微控制器GPIO&#xff08;通用輸入輸出&#xff09;引腳的輸入狀態&#xff0c;特別是在STM32系列微控制器中。它們之間的主要…

洛古B4158 [BCSP-X 2024 12 月小學高年級組] 質數補全(線性篩/dfs)

B4158 [BCSP-X 2024 12 月小學高年級組] 質數補全 - 洛谷 思路1:線性篩,字符串匹配,枚舉 質數篩選 要解決這個問題&#xff0c;首先得找出指定范圍內&#xff08;這里是 1 到 10000000&#xff09;的所有質數。常用的質數篩選算法有埃拉托斯特尼篩法&#xff08;埃氏篩&#…

一周學會Pandas2 Python數據處理與分析-Pandas2讀取Excel

鋒哥原創的Pandas2 Python數據處理與分析 視頻教程&#xff1a; 2025版 Pandas2 Python數據處理與分析 視頻教程(無廢話版) 玩命更新中~_嗶哩嗶哩_bilibili Excel格式文件是辦公使用和處理最多的文件格式之一&#xff0c;相比CSV文件&#xff0c;Excel是有樣式的。Pandas2提…

NVIDIA H100 vs A100:新一代GPU架構性能對比分析

一、核心架構演進對比 ?Ampere架構&#xff08;A100&#xff09;?采用臺積電7nm工藝&#xff0c;集成540億晶體管&#xff0c;配備6,912個CUDA核心和432個第三代Tensor Core&#xff0c;支持FP16、TF32和INT8精度計算。其顯存子系統采用HBM2e技術&#xff0c;80GB版本帶寬可…

保護PCBA的不同方法:噴三防漆 vs 鍍膜

PCBA&#xff08;印刷電路板組件&#xff09;的防護工藝中&#xff0c;噴三防漆和鍍膜&#xff08;如Parylene氣相沉積&#xff09;是兩種常見技 術。它們在防護目的上類似&#xff0c;但在具體實現方式和應用場景上有顯著差異。以下從外觀、工藝、性 能、物理性質和成本五個…

VitePress 項目部署 cloudflare page 提示 npm run build 錯誤

構建的錯誤信息如下&#xff1a; 09:52:57.975 ? YN0000: Done with warnings in 3s 120ms 09:52:58.072 Executing user command: npm run build 09:52:58.817 npm ERR! Missing script: "build" 09:52:58.818 npm ERR! 09:52:58.818 npm ERR! To see a list of …

C++學習之ORACLE③

1.集合運算符 查詢部門號是10和20的員工信息&#xff1a; &#xff1f;思考有幾種方式解決該問題 &#xff1f; SQL> select * from emp where deptno in(10, 20) SQL> select * from emp where deptno10 or deptno20 集合運算&#xff1a; Select * from emp …

人工智能之數學基礎:復矩陣

本文重點 復矩陣是線性代數中以復數為元素的矩陣,是實矩陣在復數域上的自然推廣。與實矩陣相比,復矩陣在數學性質、運算規則和應用場景上具有獨特性,尤其在量子力學、信號處理、控制理論等領域發揮關鍵作用。 復矩陣的定義與表示 定義:復矩陣指的是元素含有復數的矩陣。…

華清遠見成都中心嵌入式學習總結

一、Linux 基礎入門 課程首先介紹了 Linux 系統的六大特性&#xff0c;包括開源、免費、可裁剪等核心優勢。重點講解了文件系統結構&#xff0c;強調根目錄&#xff08;/&#xff09;作為唯一入口的樹狀結構。通過實操學習了 pwd、ls、cd 等基礎命令&#xff0c;掌握了絕對路徑…

linux安裝ollama

倆種方式都可 一、linux通過docker安裝ollama鏡像 1.下載安裝ollama鏡像 # 安裝 Docker sudo yum install docker sudo systemctl start docker#docker查看所有容器 docker ps -a # 查看所有容器# docker查看指定容器 docker ps -a |grep ollama# 創建模型存儲目錄&#xff…

Redis 學習目標

&#x1f3af; Redis 學習目標&#xff08;開發者視角&#xff09; ? 一、學習完成后能掌握的核心能力&#xff1a; 分類具體內容&#x1f4e6; 基礎能力熟練掌握 Redis 五大數據結構&#xff08;String、List、Hash、Set、ZSet&#xff09;&#xff0c;會用也會選對場景&am…

gerrit配置及使用git-lfs

gerrit服務器端配置 下載git-lfs插件 登錄Dashboard [Jenkins] (gerritforge.com)&#xff0c;下載對應版本的插件 配置gerrit 將下載的lfs.jar插件放到${GERRIT_SITE}/plugins/下面為所有倉庫啟用git-lfs 此步驟需要修改 All-projects 倉庫配置&#xff0c;步驟如下 1、克隆倉…

深入理解 Linux PATH 環境變量:配置與優化!!!

深入理解 Linux PATH 環境變量&#xff1a;配置與優化 &#x1f680; 歡迎來到 Linux 環境變量的奇妙世界&#xff01;今天我們來聊聊那個讓命令行如魚得水的幕后英雄——PATH 環境變量&#xff01;&#x1f60e; 通過這篇博客&#xff0c;你將學會如何配置它、優化它&#xff…

如何在AMD MI300X 服務器上部署 DeepSeek R1模型?

DeepSeek-R1憑借其深度推理能力備受關注&#xff0c;在語言模型性能基準測試中可與頂級閉源模型匹敵。 AMD Instinct MI300X GPU可在單節點上高效運行新發布的DeepSeek-R1和V3模型。 用戶通過SGLang優化&#xff0c;將MI300X的性能提升至初始版本的4倍&#xff0c;且更多優化將…

簡化DB操作:Golang 通用倉庫模式

介紹 本代碼包提供一個用于數據庫操作的通用倉庫 (GenericRepository)&#xff0c;利用 Golang 和 GORM (Go ORM) 實現。該倉庫設計用于簡化數據庫的 CRUD (創建、讀取、更新、刪除) 操作&#xff0c;支持批處理、沖突處理、分頁查詢等高級功能。 主要功能 創建記錄 (Create…

JavaWeb 課堂筆記 —— 08 請求響應

本系列為筆者學習JavaWeb的課堂筆記&#xff0c;視頻資源為B站黑馬程序員出品的《黑馬程序員JavaWeb開發教程&#xff0c;實現javaweb企業開發全流程&#xff08;涵蓋SpringMyBatisSpringMVCSpringBoot等&#xff09;》&#xff0c;章節分布參考視頻教程&#xff0c;為同樣學習…

雙引擎驅動:解密音視頻體驗的QoS技術底座與QoE感官革命

QoS 定義&#xff1a;QoS&#xff08;Quality of Service&#xff0c;服務質量&#xff09;衡量音視頻傳輸技術層面的性能表現&#xff0c;聚焦網絡傳輸和系統處理能力&#xff0c;通過客觀指標量化服務質量。核心指標 碼率/帶寬&#xff1a;數據傳輸速率上限&#xff0c;直接…

Stable Diffusion + Contronet,調參實現LPIPS最優(帶生成效果+指標對比)——項目學習記錄

目錄 前言 一、數據集&#xff1a;圖像文本&#xff0c;部分選取于DeepFashion 二、優化一&#xff0c;img2img 三、優化二&#xff0c;微調sd參數 四、優化三&#xff0c;dreamshaper優化 五、優化四&#xff0c;sdv1.5contronet 六、問題探索歷程 1. 從 SDXL 到輕量化模…