
关于
前端应用与后端 API 集成的生产级模式,包括竞态条件处理、请求取消、重试策略、错误规范化和 UI 状态管理。
name: frontend-api-integration-patterns description: "前端应用与后端 API 集成的生产级模式,包括竞态条件处理、请求取消、重试策略、错误规范化和 UI 状态管理。" category: frontend risk: safe source: community date_added: "2026-04-23" author: avij1109 tags:
- frontend
- api-integration
- javascript
- react
- async tools:
- claude
- cursor
- gemini
- codex
前端 API 集成模式
概述
此技能提供前端应用与后端 API 集成的生产级模式。
大多数前端问题不是因为 API 调用困难,而是因为异步行为处理不当 — 导致竞态条件、过期数据、重复请求和糟糕的用户体验。
此技能专注于正确性、弹性和用户体验,而不仅仅是让 API 调用能工作。
何时使用此技能
- 将前端应用(React、React Native、Vue 等)连接到后端 API 时
- 集成 ML/AI 端点(
/predict、/recommend)时 - 在 UI 中处理异步数据时
- 修复过期数据、UI 闪烁或重复请求时
- 设计可扩展的前端 API 层时
核心模式
1. API 层(关注点分离)
集中 API 逻辑并规范化错误。
export class ApiError extends Error {
constructor(message, status, payload = null) {
super(message);
this.name = "ApiError";
this.status = status;
this.payload = payload;
}
}
export const apiClient = async (url, options = {}) => {
const res = await fetch(url, {
headers: { "Content-Type": "application/json" },
...options,
});
if (!res.ok) {
let payload = null;
try {
payload = await res.json();
} catch (_) {}
throw new ApiError(
payload?.message || "Request failed",
res.status,
payload
);
}
// 安全处理空响应(例如 204 No Content)
if (res.status === 204) return null;
const text = await res.text();
return text ? JSON.parse(text) : null;
};
2. 竞态安全的状态管理
防止过期响应覆盖新数据。
useEffect(() => {
let cancelled = false;
const load = async () => {
try {
setLoading(true);
setError(null);
const result = await getUser();
if (!cancelled) setData(result);
} catch (err) {
if (!cancelled) setError(err.message);
} finally {
if (!cancelled) setLoading(false);
}
};
load();
return () => {
cancelled = true;
};
}, []);
对非 fetch 异步逻辑使用取消标志。对网络请求,优先使用 AbortController。
3. 请求取消(AbortController)
取消进行中的请求以避免内存泄漏和过期更新。
useEffect(() => {
const controller = new AbortController();
const load = async () => {
try {
const data = await getUser({ signal: controller.signal });
setData(data);
} catch (err) {
if (err.name === "AbortError") return;
setError(err.message);
}
};
load();
return () => controller.abort();
}, [userId]);
4. 指数退避重试
仅重试瞬态故障(5xx 或网络错误)。
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
const fetchWithBackoff = async (fn, retries = 3, delay = 300) => {
try {
return await fn();
} catch (err) {
const isAbort = err.name === "AbortError";
const isHttpError = typeof err.status === "number";
const isRetryable = !isAbort && (!isHttpError || err.status >= 500);
if (retries <= 0 || !isRetryable) throw err;
const nextDelay = delay * 2 + Math.random() * 100;
await sleep(nextDelay);
return fetchWithBackoff(fn, retries - 1, nextDelay);
}
};
5. 防抖 API 调用
避免过多的 API 调用(例如搜索输入)。
const useDebounce = (value, delay = 400) => {
const [debounced, setDebounced] = useState(value);
useEffect(() => {
const t = setTimeout(() => setDebounced(value), delay);
return () => clearTimeout(t);
}, [value, delay]);
return debounced;
};
6. 请求去重
防止跨组件的重复 API 调用。
const inFlight = new Map();
export const dedupedFetch = (key, fn) => {
if (inFlight.has(key)) return inFlight.get(key);
const promise = fn().finally(() => inFlight.delete(key));
inFlight.set(key, promise);
return promise;
};
示例
示例 1:带取消的 ML 预测
const controllerRef = useRef(null);
const handlePredict = async (input) => {
controllerRef.current?.abort();
controllerRef.current = new AbortController();
try {
const result = await fetchWithBackoff(() =>
apiClient("/predict", {
method: "POST",
body: JSON.stringify({ input }),
signal: controllerRef.current.signal,
})
);
setPrediction(result);
} catch (err) {
if (err.name !== "AbortError") setError(err.message);
}
};
兼容工具
Claude CodeCursor
标签
前端开发