需求简介

现在要对树型组件的叶子节点点击事件进行日志记录,即对下图红框中【选中】的部分进行记录,这里面就存在一个问题,直接点击叶子节点没什么问题,点击一次,就选中一次叶子节点,可以执行一次日志记录接口。但是点击非叶子节点,是会连带着把其所属的所有叶子节点全部选中的,这就等于是在极短的时间内,需要运行可能很多次的服务请求。这就会带来2个问题:1是客户端频繁请求,浪费网络资源,2是服务器可能吃不消。
image.png

解决思路

图解

演示图.pptx
创建2个数组。
1个作为临时队列,所有选中叶子节点的数据都会往这里面存储,大小不设限;
另1个作为执行数组,它的大小是有限制的,最大为M(M可以依据实际需求自己制定)。
每隔N秒(建议3但是这种写法也是有不足的,那就是如果用户一下子选中很多,但是又很快退出当前页面,那么可能只会记录第一批,会有遗漏。这个问题目前无法完美解决,可以通过增大M的值来减少请求的次数,但是也不建议太大。从技术上我们看会有问题,但是从实际的使用场景来看,问题没有那么严重,一般用户全部勾选可能都是误操作(大批量的数据叠加没什么太大意义),如果全部勾选又很快退出页面,那基本可以完全判定属于误操作,即使没记录也没有什么大问题。
因为日志记录的根本原因是为了分析用户对于对应节点的喜好(基于有效的点击数据才能更高的分析)

代码实现(Angular写法)

  1. tmpQueue = []; // 数组点选日志-临时队列
  2. executionArray = []; // 数组点选日志-执行数组
  3. timer; // 计时器
  4. // 选中事件触发
  5. // 所有的选中叶子节点统一推入临时队列
  6. fun1() {
  7. const queueItem = {
  8. OperationTime: new Date(), // 记录选中时间
  9. PushTime: '',
  10. ModuleId: e.key, // 选中的叶子节点的id
  11. };
  12. this.tmpQueue.push(queueItem);
  13. }
  14. ngOnInit() {
  15. // 每3s执行一次(N)
  16. this.timer = setInterval(() => {
  17. // 每次最多推出长度为20的数组(M)
  18. if (this.tmpQueue.length > 0) {
  19. this.executionArray = [];
  20. this.executionArray = this.tmpQueue.splice(-20, 20); // 取出后20个,先进先出
  21. const tempDate = new Date(); // 记录推送的时间
  22. this.executionArray.forEach(element => {
  23. element.PushTime = tempDate;
  24. });
  25. // 构建日志参数
  26. const params = {
  27. token: '',
  28. data: this.executionArray
  29. };
  30. // 推送
  31. // …………
  32. }
  33. }, 3000);
  34. }
  35. ngOnDestroy() {
  36. // 清除timer(退出当前页面时一点要清除,避免重复添加)
  37. clearInterval(this.timer);
  38. }