JavaScript异步编程

并发执行如果await之间没有相关依赖或顺序关系,可以直接用Promise.all包裹起来并发执行// ⛔ async function loadDashboard() { const user = await fetchUser(); const posts = await fetc...

2025年1月2日
464字

并发执行

  • 如果await之间没有相关依赖或顺序关系,可以直接用Promise.all包裹起来并发执行
// ⛔
async function loadDashboard() {
  const user = await fetchUser();
  const posts = await fetchPosts();
  const notifications = await fetchNotifications();
}
// ✅ 并发执行
async function loadDashboard() {
  const [user, posts, notifications] = await Promise.all([
    fetchUser(),
    fetchPosts(),
    fetchNotifications()
  ]);
}

以下情况不建议使用并发执行:

  • 依赖关系:如果一个请求需要另一个请求返回的数据,就必须顺序执行。
  • 竞态条件:如果多个请求会同时修改某个共享资源,可能导致数据不一致。
  • 资源限制:并发过多会给服务器或浏览器带来压力。

学会在try块中抛出错误

    • throw new Error(`HTTP error! status: ${response.status}`);
    • throw new ApiError('Failed to fetch critical data', { cause: error });

轮询请求异步接口

// ⛔ 隐形的内存杀手
async function startPolling() {
  setInterval(async () => {
    const data = await fetchData();
    updateUI(data);
  }, 5000);
}

存在以下问题:

  • 组件或页面卸载后依然在轮询
  • 如果 fetchData() 执行得很慢,可能会同时发起多次请求
  • 更新 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,可以在需要时终止请求并及时释放资源,更好地控制组件的生命周期和内存占用。

文章评论区

欢迎留言交流

未登录,请先注册或登录后发表评论。

Leave comment