// 堆代码 duidaima.com // 🚫 不推荐 async function loadDashboard() { const user = await fetchUser(); const posts = await fetchPosts(); const notifications = await fetchNotifications(); }如果每个请求都要 200ms,这里就总共要 600ms,给用户的体验自然不佳。
// ✅ 建议用 Promise.all async function loadDashboard() { const [user, posts, notifications] = await Promise.all([ fetchUser(), fetchPosts(), fetchNotifications() ]); }同样是获取用户、帖子和通知,响应速度立刻加快三倍左右。不过,并发并非万能。
// 🚫 并行可能导致竞态问题 await Promise.all([ updateUserProfile(userId, { name: 'New Name' }), updateUserProfile(userId, { email: 'new@email.com' }) ]); // ✅ 先后执行以防数据冲突 const user = await updateUserProfile(userId, { name: 'New Name' }); await updateUserProfile(userId, { email: 'new@email.com' });如果并行更新同一个用户资料,服务器可能会出现覆盖数据的情况。必须根据业务逻辑判断能否并发执行。
// 🚫 隐形错误 async function fetchData() { try { const response = await fetch('/api/data'); return await response.json(); } catch (error) { console.error(error); return null; // 🚨 难以排查的隐患 } }看似“处理”了错误,但实际上把错误原因都藏起来了。网络断了?JSON 解析失败?服务器返回 500?外部代码只能拿到 null,毫无头绪。
// ✅ 有针对性的错误处理 async function fetchData(options = {}) { const { isCritical = true } = options; try { const response = await fetch('/api/data'); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return await response.json(); } catch (error) { console.error('Data fetch failed:', error); if (isCritical) { // 对关键数据抛出自定义错误,交由更高层级处理 throw new ApiError('Failed to fetch critical data', { cause: error }); } else { // 非关键数据,可返回一个降级的默认值 return { type: 'fallback', data: [] }; } } } // 用法示例: // 关键数据(出错时会抛异常) const userData = await fetchData({ isCritical: true }); // 非关键通知数据(出错时返回空列表) const notifications = await fetchData({ isCritical: false });这样就能同时兼顾稳定性和可维护性。关键数据绝不能“悄悄失败”,而次要功能可以“优雅退化”。
// 🚫 隐形的内存杀手 async function startPolling() { setInterval(async () => { const data = await fetchData(); updateUI(data); }, 5000); }表面看上去没什么问题,但这样会导致:
3.更新 UI 时,目标 DOM 甚至可能已经被移除
class PollingManager { constructor(options = {}) { this.controller = new AbortController(); this.interval = options.interval || 5000; } async start() { while (!this.controller.signal.aborted) { try { const response = await fetch('/api/data', { signal: this.controller.signal }); const data = await response.json(); updateUI(data); // 等待下一次轮询 await new Promise(resolve => setTimeout(resolve, this.interval)); } catch (error) { if (error.name === 'AbortError') { console.log('Polling stopped'); return; } console.error('Polling error:', error); } } } stop() { this.controller.abort(); } } // 在 React 组件中使用 function DataComponent() { useEffect(() => { const poller = new PollingManager({ interval: 5000 }); poller.start(); // 组件卸载时停止轮询 return () => poller.stop(); }, []); return <div>Data: {/* ... */}</div>; }通过使用 AbortController,可以在需要时终止请求并及时释放资源,更好地控制组件的生命周期和内存占用。
async function fetchWithRetry(url, options = {}) { const { maxRetries = 3, backoff = 1000 } = options; for (let attempt = 0; attempt < maxRetries; attempt++) { try { return await fetch(url); } catch (error) { if (attempt === maxRetries - 1) throw error; // 退避延迟,指数增长 await new Promise(r => setTimeout(r, backoff * Math.pow(2, attempt))); } } }除了基本的指数退避,还可以考虑:
class ResourceManager { cleanup() { // 在这里集中处理各种操作的终止和释放 } }真实场景中的模式
const { data, loading, error } = useAsyncData(() => fetchUserData());这样可以:
在组件卸载时自动清理
const syncManager = new DataSyncManager({ onSync: (data) => updateUI(data), onError: (error) => showError(error), syncInterval: 5000 });几条核心原则
.在可能的情况下提供取消或中断操作
.组件卸载时,保证所有定时器、订阅或轮询都能停止
考虑扩展性:当用户量或请求量激增时,如何保证依旧能流畅运行?如果某些服务变慢甚至挂掉,该如何部分降级?