You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 15中如何获取路由跳转后含API调用的页面加载时间?

解决方案:全局跟踪API请求+资源加载完成状态

要实现所有API响应、脚本/图片等资源加载完成后触发函数,同时支持路由跳转场景,推荐采用「全局API请求拦截+Performance资源监控」的组合方案,无需逐个组件手动跟踪,具体实现如下:

核心思路

  1. 全局拦截所有API请求,维护一个活跃请求计数器,统计未完成的API数量
  2. 用PerformanceObserver监听所有资源(脚本、图片、样式等)的加载状态,确认所有资源加载完毕
  3. 当「活跃API计数器归0」且「所有资源加载完成」时,触发目标函数;路由跳转时重置状态,重新监听

步骤1:封装API请求,跟踪活跃请求数

以Axios为例(Fetch可参考类似逻辑),在全局请求/响应拦截器中维护请求计数器:

// api/tracker.ts
import axios from 'axios';

let activeApiRequests = 0;

export const ApiTracker = {
  increment: () => activeApiRequests++,
  decrement: () => {
    activeApiRequests--;
    checkAllComplete();
  },
  reset: () => activeApiRequests = 0,
  getActiveCount: () => activeApiRequests
};

// 创建全局Axios实例
export const apiClient = axios.create({
  baseURL: '/api'
});

// 请求拦截器:开始请求时增加计数器
apiClient.interceptors.request.use(
  (config) => {
    ApiTracker.increment();
    return config;
  },
  (error) => {
    ApiTracker.decrement();
    return Promise.reject(error);
  }
);

// 响应拦截器:请求结束(成功/失败)时减少计数器
apiClient.interceptors.response.use(
  (response) => {
    ApiTracker.decrement();
    return response;
  },
  (error) => {
    ApiTracker.decrement();
    return Promise.reject(error);
  }
);

步骤2:用PerformanceObserver监控资源加载

通过PerformanceObserver监听所有资源的加载状态,确认所有资源(脚本、图片、字体等)都已加载完成:

// resource/tracker.ts
let allResourcesLoaded = false;

export const ResourceTracker = {
  setLoaded: () => {
    allResourcesLoaded = true;
    checkAllComplete();
  },
  reset: () => allResourcesLoaded = false,
  isLoaded: () => allResourcesLoaded
};

// 初始化资源监控
export function initResourceObserver() {
  const observer = new PerformanceObserver((entryList) => {
    // 过滤出未完成加载的资源条目
    const incompleteResources = entryList.getEntries().filter(entry => 
      entry.entryType === 'resource' && (entry.responseEnd === 0 || entry.loadingEnd === 0)
    );
    // 没有未完成的资源时,标记为已加载
    if (incompleteResources.length === 0) {
      ResourceTracker.setLoaded();
    }
  });

  // 监听所有资源类型的加载事件
  observer.observe({ entryTypes: ['resource'] });
}

步骤3:合并状态,触发目标函数

编写全局检查逻辑,当API和资源都完成时触发指定函数:

// completion/checker.ts
import { ApiTracker } from '../api/tracker';
import { ResourceTracker } from '../resource/tracker';

// 存储要触发的目标函数
let targetCallback: (loadTime: number) => void;

export function setCompletionCallback(callback: (loadTime: number) => void) {
  targetCallback = callback;
}

export function checkAllComplete() {
  // 当活跃API为0且所有资源加载完成时触发
  if (ApiTracker.getActiveCount() === 0 && ResourceTracker.isLoaded()) {
    // 获取当前时间戳(从页面初始化开始的耗时)
    const loadTime = performance.now();
    targetCallback?.(loadTime);
    
    // 重置状态,避免重复触发(路由跳转时会重新初始化)
    ApiTracker.reset();
    ResourceTracker.reset();
  }
}

步骤4:路由跳转时重置状态

以React Router为例,在路由切换时重新初始化监控,确保每次页面跳转都能正确统计:

// App.tsx
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
import { initResourceObserver } from './resource/tracker';
import { setCompletionCallback } from './completion/checker';

function App() {
  const location = useLocation();

  useEffect(() => {
    // 路由切换时重置所有跟踪状态
    initResourceObserver();
    setCompletionCallback((loadTime) => {
      // 这里执行你的业务逻辑,比如上报加载时间、更新UI等
      console.log('所有资源+API加载完成,总耗时:', loadTime.toFixed(2), 'ms');
    });
  }, [location.pathname]);

  return (
    <div className="app">
      {/* 你的路由内容 */}
    </div>
  );
}

export default App;

边界情况处理

  • 动态加载资源:PerformanceObserver会自动监听后续动态加载的资源(比如懒加载图片、异步脚本),无需额外处理
  • API请求失败:拦截器中已处理失败场景,确保计数器正确递减
  • 重复触发:每次触发后自动重置状态,路由跳转时重新初始化,避免重复执行回调

内容的提问来源于stack exchange,提问作者Osama Naaz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 17:55:32