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
相关产品推荐
相关产品推荐

