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

JavaScript批量API调用实现:事件日志器的两个优化需求

事件日志器实现方案

需求目标

  • 采用类似防抖的方式,将点击事件分组后一次性上报
  • 确保第一批请求成功后,再发送下一批请求,避免并发请求冲突

完整实现代码

HTML

<div id="parent">
  <div style="background-color: rgb(255, 255, 0)" class="square"></div>
  <div style="background-color: rgb(0, 255, 0)" class="square"></div>
  <div style="background-color: rgb(0, 255, 255)" class="square"></div>
  <div style="background-color: rgb(128, 0, 128)" class="square"></div>
  <div style="background-color: rgb(255, 0, 255)" class="square"></div>
</div>

CSS

.square {
  height: 70px !important;
  width: 70px !important;
  padding: 10px;
  border: 1px solid;
}

#parent {
  display: flex;
}

JavaScript

// 模拟API请求函数,替换为实际接口调用即可
async function sendRequest(events) {
  console.log("上报事件:", events);
  return new Promise(resolve => {
    setTimeout(() => {
      console.log("上报成功");
      resolve({ status: "success" });
    }, 1000);
  });
}

class EventLogger {
  constructor(batchLimit = 1000, debounceDelay = 1000) {
    this.timerId = null;
    this.isSending = false; // 标记当前是否正在发送请求
    this.events = []; // 实例内部存储待上报事件,避免全局污染
    this.batchLimit = batchLimit; // 单批次最大事件数
    this.debounceDelay = debounceDelay; // 防抖延迟时长
  }

  async logEvent(event, data) {
    this.events.push(data);
    console.log("当前待上报事件数:", this.events.length);

    // 清除之前的防抖定时器
    clearTimeout(this.timerId);

    // 事件数达到批次上限时,立即触发上报
    if (this.events.length >= this.batchLimit) {
      await this.sendBatch();
      return;
    }

    // 未达上限则启动防抖定时器,延迟后自动上报
    this.timerId = setTimeout(() => {
      this.sendBatch();
    }, this.debounceDelay);
  }

  async sendBatch() {
    // 正在发送请求或无待上报事件时,直接返回
    if (this.isSending || this.events.length === 0) return;

    this.isSending = true;
    const batchEvents = [...this.events]; // 复制当前批次事件,避免上报过程中新增事件干扰
    this.events = []; // 清空队列,接收新事件

    try {
      await sendRequest(batchEvents);
    } catch (error) {
      console.error("上报失败:", error);
      // 上报失败时将事件重新放回队列,等待重试
      this.events.unshift(...batchEvents);
    } finally {
      this.isSending = false;
      // 队列中有新事件时,立即触发下一批上报
      if (this.events.length > 0) {
        this.sendBatch();
      }
    }
  }
}

const eventLog = new EventLogger(2);

window.addEventListener("load", () => {
  const parentElem = document.querySelector("#parent");
  parentElem.addEventListener("click", (event) => {
    const targetElem = event.target;
    if (targetElem.className === "square") {
      const bgColor = targetElem.style.backgroundColor;
      const eventObj = {
        event: "click",
        timeStamp: new Date().toISOString(),
        url: location.hostname,
        data: { color: bgColor },
      };
      eventLog.logEvent("click", eventObj);
    }
  });
});

关键实现说明

1. 防抖+批次分组上报

  • 每次调用logEvent时将事件加入队列,同时清除之前的防抖定时器
  • 当事件数量达到batchLimit(示例中为2)时,立即触发批量上报
  • 未达批次上限时,启动防抖定时器,延迟后自动合并上报短时间内的多次点击事件

2. 串行请求控制

  • 通过isSending状态标记避免并发请求,当前请求未完成时不会触发新的上报
  • 上报完成(成功/失败)后重置状态,若队列中有新事件则自动触发下一批上报
  • 上报失败时将事件重新放回队列,保证事件不丢失

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 03:30:00