当前位置: 首页 > news >正文

fetch函数全面解析

fetch函数全面解析

fetch是现代 JavaScript 生态中处理网络请求的核心 API,凭借其基于 Promise 的简洁语法和强大功能,已逐步取代传统的XMLHttpRequest,成为 Web 开发的标准选择。本文将从基础概念、核心特性到企业级实践,全面解析fetch的使用与优化。

一、fetch是内置函数吗?
1.1 起源与标准化
fetch是现代浏览器和 JavaScript 运行环境的内置函数,其标准化进程如下:

时间

事件

说明

2015年

首次引入浏览器

作为浏览器原生 API 出现,替代传统的XMLHttpRequest

2015年

纳入 WHATWG Fetch Living Standard

成为国际标准,确保跨浏览器兼容性

2022年

Node.js 18+ 原生支持

无需额外库即可在 Node.js 中使用fetch

2023年

Deno 1.0 内置支持

作为 Deno 的核心 API,开箱即用

1.2 环境支持情况
fetch已广泛支持主流开发环境:

环境

支持情况

说明

现代浏览器

✅ 完全支持

Chrome 42+、Firefox 39+、Safari 10.1+、Edge 14+ 及以上版本

Node.js

✅ v18+ 原生支持

v18 前需通过node-fetch或undici库模拟

Deno

✅ 内置支持

无需额外配置

Web Workers

✅ 支持

包括 Service Workers 等 Worker 线程

React Native

✅ 支持

基于平台原生实现(如 iOS 的 URLSession、Android 的 OkHttp)

二、fetch核心特性详解
2.1 基本语法
fetch基于 Promise,返回一个解析为Response对象的 Promise:

const response = await fetch(resource, options);

2.2 参数解析
参数

类型

说明

示例

resource

string/URL/Request

请求的资源地址或Request对象

'/api/users'或new URL('https://api.example.com')

options

Object

可选配置项(如请求方法、头信息、请求体等)

{ method: 'POST', headers: {...} }

2.3 常用配置选项
options支持丰富的配置,以下是常见参数:

{method: 'GET', // 请求方法(GET/POST/PUT/DELETE 等)headers: { // 请求头对象'Content-Type': 'application/json','Authorization': 'Bearer token'},body: JSON.stringify(data), // 请求体(仅 POST/PUT 等非 GET 请求有效)cache: 'no-cache', // 缓存策略(`default`/`no-store`/`reload` 等)credentials: 'include', // 跨域时是否携带 Cookie(`omit`/`same-origin`/`include`)mode: 'cors', // 跨域模式(`cors`/`no-cors`/`same-origin`)redirect: 'follow', // 重定向处理(`follow`/`error`/`manual`)signal: abortController.signal // 中止请求的信号(通过 `AbortController` 生成)}

2.4Response对象详解
fetch返回的Response对象包含响应的核心信息与方法:

属性/方法

类型

说明

response.ok

boolean

状态码在 200-299 时为true

response.status

number

HTTP 状态码(如 200、404、500)

response.statusText

string

状态文本(如 "OK"、"Not Found")

response.headers

Headers

响应头对象(可通过get()方法获取具体头信息)

response.url

string

最终请求的 URL(处理重定向后)

response.json()

Promise

解析响应体为 JSON 对象

response.text()

Promise

解析响应体为纯文本

response.blob()

Promise

解析响应体为二进制大对象(适用于文件下载)

response.arrayBuffer()

Promise

解析响应体为二进制数组缓冲区(适用于底层数据处理)

response.clone()

Response

克隆响应对象(解决响应体只能读取一次的问题)三、企业级使用模式
3.1 基本数据获取

async function fetchUsers() {

try {

const response = await fetch('/api/users');

// 检查响应状态

if (!response.ok) {

throw new Error(HTTP 错误!状态码:${response.status});

}

// 解析 JSON 数据

const users = await response.json();

return users;

} catch (error) {

console.error('请求失败:', error);

throw error; // 向上传递错误

}

}

3.2 带参数的 GET 请求
通过URLSearchParams或URL对象构造带查询参数的 URL:

async function searchProducts(query: string, limit = 10) {

// 构造 URL 对象

const url = new URL('/api/products', window.location.origin);

// 添加查询参数

url.searchParams.append('q', query);

url.searchParams.append('limit', limit.toString());

const response = await fetch(url);

return response.json();

}

3.3 POST 请求提交数据

interface User {

name: string;

email: string;

}

async function createUser(userData: User) {

const response = await fetch('/api/users', {

method: 'POST',

headers: {

'Content-Type': 'application/json',

'Authorization': Bearer ${localStorage.getItem('token')} // 携带认证令牌

},

body: JSON.stringify(userData) // 序列化请求体

});

if (!response.ok) {

const errorData = await response.json();

throw new Error(创建用户失败:${errorData.message});

}

return response.json(); // 返回创建的用户数据

}

3.4 文件上传
使用FormData对象处理文件上传:

async function uploadFile(file: File) {

const formData = new FormData();

formData.append('file', file); // 添加文件

formData.append('metadata', JSON.stringify({ // 添加元数据

uploader: 'user123',

timestamp: new Date().toISOString()

}));

const response = await fetch('/api/upload', {

method: 'POST',

body: formData

// 注意:无需手动设置 Content-Type,浏览器会自动设置为 multipart/form-data

});

return response.json();

}

3.5 请求超时控制
通过AbortController实现请求超时:

async function fetchWithTimeout(resource, options = {}, timeout = 8000) {

const controller = new AbortController();

const timeoutId = setTimeout(() => controller.abort(), timeout); // 设置超时时间

try {

const response = await fetch(resource, {

...options,

signal: controller.signal // 关联中止信号

});

clearTimeout(timeoutId); // 成功响应后清除超时

return response;

} catch (error) {

clearTimeout(timeoutId);

if (error.name === 'AbortError') {

throw new Error('请求超时');

}

throw error; // 其他错误

}

}

四、TypeScript 类型增强
4.1 响应类型安全
通过类型断言或泛型函数确保响应数据的类型安全:

interface User {

id: number;

name: string;

email: string;

}

async function fetchUser(userId: number): Promise {

const response = await fetch(/api/users/${userId});

if (!response.ok) {

throw new Error(获取用户 ${userId} 失败);

}

// 类型断言确保返回值为 User 类型

return response.json() as Promise;

}

4.2 类型安全的fetch封装
通过泛型封装通用fetch函数,提升复用性:

async function typedFetch(

url: string,

options?: RequestInit

): Promise {

const response = await fetch(url, options);

if (!response.ok) {

const errorData = await response.json();

throw new Error(errorData.message || '请求失败');

}

return response.json() as Promise;

}

// 使用示例

interface Product {

id: string;

name: string;

price: number;

}

const product = await typedFetch('/api/products/123');

五、与XMLHttpRequest的对比
特性fetchXMLHttpRequest语法基于 Promise(异步更简洁)基于事件回调(代码嵌套复杂)流式处理✅ 支持(通过ReadableStream)❌ 不支持请求中止✅ 通过AbortController✅ 通过abort()方法CORS 处理✅ 配置简单(mode/credentials)�� 需手动处理预请求(OPTIONS)进度监控❌ 原生不支持(需结合ReadableStream)✅ 支持progress事件超时设置❌ 原生不支持(需结合AbortController)✅ 支持timeout属性JSON 处理✅ 内置response.json()方法❌ 需手动JSON.parse()请求缓存✅ 支持精细控制(cache配置)�� 仅支持简单缓存策略现代特性✅ 支持 Service Workers 等❌ 不支持六、企业级最佳实践
6.1 创建 API 客户端抽象层
通过封装fetch实现统一的 API 调用逻辑,处理认证、错误等通用需求:

class ApiClient {

private baseUrl: string;

constructor(baseUrl: string) {

this.baseUrl = baseUrl;

}

// GET 请求

async get(endpoint: string): Promise {

return this.request('GET', endpoint);

}

// POST 请求

async post(endpoint: string, data: any): Promise {

return this.request('POST', endpoint, data);

}

// 通用请求方法

private async request(

method: string,

endpoint: string,

data?: any

): Promise {

const url = ${this.baseUrl}${endpoint};

const headers: Record<string, string> = {

'Content-Type': 'application/json'

};

// 添加认证令牌

const token = localStorage.getItem('authToken');

if (token) {

headers['Authorization'] = Bearer ${token};

}

const response = await fetch(url, {

method,

headers,

body: data ? JSON.stringify(data) : undefined

});

if (!response.ok) {

await this.handleError(response); // 统一错误处理

}

return response.json() as Promise;

}

// 错误处理逻辑

private async handleError(response: Response) {

let errorMessage = HTTP 错误 ${response.status};

try {

const errorData = await response.json();

if (errorData.message) {

errorMessage = errorData.message;

}

} catch {

// 响应体非 JSON 时,直接使用状态码

}

throw new Error(errorMessage);

}

}

// 使用示例

const api = new ApiClient('https://api.example.com');

const users = await api.get<User[]>('/users'); // 获取用户列表

const newUser = await api.post('/users', { name: 'Alice' }); // 创建用户

6.2 拦截器模式
通过请求/响应拦截器实现全局逻辑(如日志、认证、错误重定向):

// 请求拦截器:添加认证令牌和请求 ID

async function interceptRequest(input: RequestInfo, init?: RequestInit) {

let url = typeof input === 'string' ? input : input.url;

const options = init || {};

// 添加认证令牌

const token = localStorage.getItem('authToken');

if (token) {

options.headers = {

...options.headers,

Authorization: Bearer ${token}

};

}

// 添加请求 ID(用于日志追踪)

options.headers = {

...options.headers,

'X-Request-ID': crypto.randomUUID()

};

return { url, options };

}

// 响应拦截器:处理未授权、服务器错误等

async function interceptResponse(response: Response) {

if (response.status === 401) {

// 未授权时跳转登录页

window.location.href = '/login';

return response;

}

if (response.status >= 500) {

// 记录服务器错误日志

console.error('服务器错误:', response);

}

return response;

}

// 封装带拦截器的 fetch

const fetchWithInterceptors = async (input: RequestInfo, init?: RequestInit) => {

const { url, options } = await interceptRequest(input, init);

const response = await fetch(url, options);

return interceptResponse(response);

};

6.3 缓存策略实现
通过内存缓存减少重复请求,提升性能:

const apiCache = new Map<string, { data: any; timestamp: number }>();

async function fetchWithCache(

url: string,

options?: RequestInit,

cacheTime = 60000 // 缓存 1 分钟

): Promise {

const cacheKey = ${url}-${JSON.stringify(options)};

// 检查缓存是否有效

const cached = apiCache.get(cacheKey);

if (cached && Date.now() - cached.timestamp < cacheTime) {

return cached.data as T;

}

// 无有效缓存时发送请求

const response = await fetch(url, options);

if (!response.ok) {

throw new Error(请求失败:${response.status});

}

const data = await response.json();

// 更新缓存

apiCache.set(cacheKey, {

data,

timestamp: Date.now()

});

return data as T;

}

七、常见问题与解决方案
7.1 CORS 问题
问题:跨域请求被浏览器阻止,控制台提示“CORS 策略阻止”。解决方案:前端配置:明确设置mode: 'cors'和credentials: 'include'(如需携带 Cookie)。
后端配置:返回以下响应头:Access-Control-Allow-Origin: https://yourdomain.com // 允许的源
Access-Control-Allow-Methods: GET, POST, OPTIONS // 允许的方法Access-Control-Allow-Headers: Content-Type, Authorization // 允许的请求头Access-Control-Allow-Credentials: true // 允许携带 Cookie7.2 错误处理不完整
问题:仅检查response.ok忽略特定状态码(如 401 未授权、403 禁止访问)。解决方案:针对关键状态码添加逻辑:

async function safeFetch(url: string, options?: RequestInit) {

const response = await fetch(url, options);

if (response.status === 401) {

// 未
}

http://www.gsyq.cn/news/49215.html

相关文章:

  • 2025全球知名连接器品牌价值榜与中国企业崛起:十大品牌全景测评与选型指南
  • C# PuppeteerSharp html转pdf
  • 大气环流模式
  • 使用神经网络处理逻辑异或门问题
  • MATLAB实现光谱特征波长提取
  • 支持服务器的文件同步软件提升数据管理效率
  • 2025年重庆吊装搬运公司权威推荐榜单:起重设备/专业吊装/起重机源头公司精选
  • 2025年快装集成墙板厂家权威推荐榜单:集成墙板整装/碳晶板整装/A级防火板整装源头厂家精选
  • 2025年11月冷再生机/水泥板破碎机生产厂家推荐榜单:环硕建设领跑行业
  • 2025年11月水泥板破碎机和冷再生机供货源头厂家推荐排行榜前十名:行业权威解析江苏环硕建设有限公司
  • 基于LCMV的自适应波束形成算法仿真实现
  • maven的settings.xml
  • 2025年土陶泡菜坛直销厂家权威推荐榜单:陶瓷酒瓶/土陶酒坛/储酒坛源头厂家精选
  • 信创浪潮下,国产DevOps平台如何乘风破浪?
  • 双赢思维
  • Windows 11 系统对磁盘进行分区保姆级教程
  • 2025年知名的节能加热圈厂家最新TOP排行榜
  • 2025年热门的废水处理液体分离设备TOP实力厂家推荐榜
  • 【URP】Unity[后处理]晕影Vignette
  • 2025年知名的酶制剂浓缩设备最新TOP厂家排名
  • 2025年比较好的板材超声波探伤厂家最新推荐排行榜
  • 从 .NET Core1.0 到 .NET 10:.NET + C# 演进全景
  • 再见 Postman!一款开源免费的全能 API 客户端工具!
  • 2025安全立网销售厂家排行
  • 2025年瑜伽垫源头厂家推荐榜
  • 2025年口碑好的通风设备管道TOP品牌厂家排行榜
  • 2025年企业微信服务商综合排名TOP10:数字化转型首选指南
  • 字节串和字符串对比
  • 双北斗卫星时间同步系统:安徽京准助力基础网络建设准绳
  • 2025年11月国内可平滑替换VMware Workspace ONE产品榜:权威对比