 闽公网安备 35020302035485号
                
                闽公网安备 35020302035485号
                fetch 可以与 AbortController 搭配使用来取消请求。
	
(function() {
  const originalOpen = XMLHttpRequest.prototype.open;
  const originalSend = XMLHttpRequest.prototype.send;
  XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {
    this._url = url; // 保存请求的URL
    return originalOpen.apply(this, arguments);
  };
  XMLHttpRequest.prototype.send = function(body) {
    this.addEventListener('load', function() {
      if (this.status >= 200 && this.status < 300) {
        // 请求成功,上报成功信息
        reportRequest('success', this._url, this.status, this.responseText);
      } else {
        // 请求失败,上报失败信息
        reportRequest('failure', this._url, this.status, this.responseText);
      }
    });
    this.addEventListener('error', function() {
      // 请求错误,上报错误信息
      reportRequest('error', this._url, this.status, this.statusText);
    });
    return originalSend.apply(this, arguments);
  };
  function reportRequest(type, url, status, response) {
    // 这里进行上报,可以通过fetch或其他方式发送上报请求
    console.log(`Request ${type}: ${url}, Status: ${status}, Response: ${response}`);
    // 例子:fetch('/report', { method: 'POST', body: JSON.stringify({ type, url, status, response }) })
  }
})();
那fetch如何实现监听呢?同样也是重写。(function() {
  const originalFetch = window.fetch;
  window.fetch = function() {
    const args = arguments;
    const url = args[0];
     // 堆代码 duidaima.com
    return originalFetch.apply(this, arguments)
      .then(response => {
        if (response.ok) {
          // 请求成功,上报成功信息
          response.clone().text().then(responseText => {
            reportRequest('success', url, response.status, responseText);
          });
        } else {
          // 请求失败,上报失败信息
          response.clone().text().then(responseText => {
            reportRequest('failure', url, response.status, responseText);
          });
        }
        return response;
      })
      .catch(error => {
        // 请求错误,上报错误信息
        reportRequest('error', url, 0, error.message);
        throw error;
      });
  };
  function reportRequest(type, url, status, response) {
    // 这里进行上报,可以通过fetch或其他方式发送上报请求
    console.log(`Request ${type}: ${url}, Status: ${status}, Response: ${response}`);
    // 例子:fetch('/report', { method: 'POST', body: JSON.stringify({ type, url, status, response }) })
  }
})();
看到这里,其实实现类似ARMS这样的API请求,很简单,ARMS底层一定也是依赖类似这样的代码块来实现原子能力,在此基础上,设计了一套可插拔、模块化的系统监控架构,来进行系统全方位的监听。import TraceApiPlugin from '@ali/trace-plugin-api';
import TracePerfPlugin from '@ali/trace-plugin-perf';
import TracePvPlugin from '@ali/trace-plugin-pv';
import TraceResourceErrorPlugin from '@ali/trace-plugin-resource-error';
import TraceSdk from '@ali/trace-sdk';
import { isProd } from './constants';
const traceEnv = isProd ? 'prod' : 'test';
const trace = TraceSdk({
  pid: 'relax-drink', // 必填 请在https://arms.alibaba-inc.com/arms/project/create 申请项目ID
  errorEnable: true, // 非必填 默认已经开启了js报错,若关闭则设置errorEnable:false
  env: traceEnv, // 可选 prod | pre | daily | string
  ignoreErrors: [/^Script error\.?$/], // 可选,用法参考"初始化配置说明"
  aplusUrl: 's-gm.mmstat.com', // 可选 默认s-gm.mmstat.com, 海外(新加坡)埋点配置 sg.mmstat.com
  plugins: [
    // 使用插件
    [TracePvPlugin, { autoPV: false }],
    [TraceApiPlugin, { sampling: 0.1 }], // 接口监控插件
    [TracePerfPlugin, { enableLCP: true }],
    [TraceResourceErrorPlugin], // 前端资源异常监控插件
  ],
  useSendBeacon: false,
});
// 执行
trace.install();
代码块中包含了ARMS的其他能力,包括js error、性能、资源的监控,我们本节只基于接口请求做示例。function TraceSdk(config) {
  // 默认配置
  const defaultConfig = {
    errorEnable: true,
    env: 'prod',
    aplusUrl: 's-gm.mmstat.com',
    useSendBeacon: false,
    ignoreErrors: [],
    plugins: [],
  };
  // 合并用户提供的配置和默认配置
  const finalConfig = { ...defaultConfig, ...config };
  // 初始化插件
  function initializePlugins(plugins) {
    plugins.forEach(([PluginConstructor, options]) => {
      const plugin = new PluginConstructor(options);
      plugin.initialize();
    });
  }
  // 安装SDK
  function install() {
    console.log('Trace SDK 安装中...');
    setupErrorHandling();
    initializePlugins(finalConfig.plugins);
  }
  // 设置错误处理(简单实现)
  function setupErrorHandling() {
    if (finalConfig.errorEnable) {
      window.addEventListener('error', (event) => {
        const errorMessage = event.message;
        if (
          !finalConfig.ignoreErrors.some((regex) => regex.test(errorMessage))
        ) {
          console.error('捕获到错误:', errorMessage);
          // 可在此执行错误报告逻辑
        }
      });
    }
  }
  // 公开的API
  return {
    install,
  };
}
// 示例插件构造函数(模拟)
function TraceApiPlugin(options) {
  this.options = options || {};
  this.initialize = function () {
    const originalOpen = XMLHttpRequest.prototype.open;
    const originalSend = XMLHttpRequest.prototype.send;
    XMLHttpRequest.prototype.open = function (method, url, async, user, pass) {
      this._url = url; // 保存请求的URL
      return originalOpen.apply(this, arguments);
    };
    XMLHttpRequest.prototype.send = function (body) {
      this.addEventListener('load', function () {
        if (this.status >= 200 && this.status < 300) {
          // 请求成功,上报成功信息
          reportRequest('success', this._url, this.status, this.responseText);
        } else {
          // 请求失败,上报失败信息
          reportRequest('failure', this._url, this.status, this.responseText);
        }
      });
      this.addEventListener('error', function () {
        // 请求错误,上报错误信息
        reportRequest('error', this._url, this.status, this.statusText);
      });
      return originalSend.apply(this, arguments);
    };
    function reportRequest(type, url, status, response) {
      // 这里进行上报,可以通过fetch或其他方式发送上报请求
      console.log(
        `Request ${type}: ${url}, Status: ${status}, Response: ${response}`,
      );
      // 例子:fetch('/report', { method: 'POST', body: JSON.stringify({ type, url, status, response }) })
    }
  };
}
如果想启用更多的能力,则ARMS内部肯定会有类似TraceJsErrorPlugin、TracePerfPlugin等,直接在初始化阶段注入到TraceSDK实例初始化即可。