历险记 ---- Performance

前端监控 API 时使用了 Performace 接口,但是目前大部分文章都只是罗列其本身的属性或方法,实战中使用的场景比较少,我自己也走了些弯路,现在记录下这些,大家可以一起来讨论下。

先讲一下使用场景,页面加载后记录后台接口,页面跳转前也记录后台接口。在记录接口前需要区分接口是否需要已经被记录过,不会重复记录。

就如何标记接口数据是否已被记录,自己尝试了四种方式

  1. 对已记录的接口添加 outdate 字段并标记为 true
  2. 使用 performace.mark 方法打标记,每次只记录最后一个标记后的接口
  3. 使用 performace.mark 方式打标记,但是比较的是比 mark 的 startTime 字段大的 responseEnd 字段 (比较绕后续看代码吧)
  4. 使用全局变量记录下发送的接口数量,每次先根据变量截取 performace.getEntries() 返回的数组再更新变量的值
1、2 两种方式被淘汰了,3 当时因时间关系只处理想法阶段,后测试可行,4 是目前采用的

下面根据方式来讲讲遇到的问题

1、performace 只读

虽然现在大部分的浏览器支持在 PerformaceEntry 中增加字段,但有些浏览器不允许,如 IE 11、chrome 的部分版本,MDN 中目前也是标记为 只读

  const entries = performance.getEntries();
  // 下面方法只筛选了发送的接口,需要过滤掉发送埋点请求的接口
  const freshEntries = entries.filter(
    item =>
      !item.outdate &&
      item.entryType === "resource" &&
      item.initiatorType === "xmlhttprequest"
  );

  entries.forEach(item => {
    item.outdate = true;
  });

  return freshEntries || [];

2、打标记

在打标记时已发送请求但未返回数据的接口,会在接口返回后会出现在标记前。并不会如预期的出现在标记后,原因是 PerformaceEntry 是根据 startTime 排序的

  const entries = performance.getEntries();
  entries.reverse();

  if (entries[0].entryType === 'mark' && entries[0].name === 'MARKNAME') {
    return [];
  }

  // 为防止在这期间有接口请求,先打标记再处理数据
  performance.mark('MARKNAME');

  const endIndex = entries.findIndex(i => i.entryType === 'mark' && i.name === 'MARKNAME');

  const freshEntries = entries
    .slice(0, endIndex)
    .filter(item => item.entryType === 'resource' && item.initiatorType === 'xmlhttprequest');

  return freshEntries || [];

3、打标记后对比 mark 时间和接口返回时间

直接上代码吧!更简单直接

  const entries = performance.getEntries();

  const markList = performance.getEntriesByName('MARKNAME');
  markList.reverse();
  const markTime = markList.length ? markList[0].startTime : 0;

  // 为防止在这期间有接口请求,先打标记再处理数据
  performance.mark('MARKNAME');

  const freshEntries = entries.filter(
    item =>
      item.entryType === "resource" &&
      item.initiatorType === "xmlhttprequest" &&
      item.responseEnd > markTime // 对比接口的返回时间和上次打标记的时间
  );

  return freshEntries || [];
项目采用的是typeScript,打包时报 Property 'responseEnd' does not exist on type 'PerformanceEntry',对 ts 语法也不是很熟,就先放弃了

4、记录已发送的接口数量

这个方式很简单,之所以一开始的时候未采用,是不想创建全局变量,还要截取数组,给字段赋值。后来因时间问题也就只能这样了。

  // 初始化时,alreadySendApiNum 设置为 0 
  const entries = performance.getEntries();

  const freshEntries = entries
    .filter(item => item.entryType === 'resource' && item.initiatorType === 'xmlhttprequest');

  return freshEntries || [];

  freshEntries.slice(alreadySendApiNum)... // 记录接口数据

  alreadySendApiNum = freshEntries.length;

对 performance 的了解有限,先到此为止
希望有帮助到屏幕前的你,也望不吝赐教

如有侵权请告知

你可能感兴趣的:(历险记 ---- Performance)