闽公网安备 35020302035485号

// 堆代码 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
});
几条核心原则.在可能的情况下提供取消或中断操作
.组件卸载时,保证所有定时器、订阅或轮询都能停止
考虑扩展性:当用户量或请求量激增时,如何保证依旧能流畅运行?如果某些服务变慢甚至挂掉,该如何部分降级?