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

Angular中使用lodash.debounce包裹函数后失效,如何解决?

问题描述

我编写了一个响应window的click、mousemove、keydown事件的函数,该函数会调用AuthService的sessionExtention接口。不使用防抖时功能正常,但频繁触发事件会导致服务器崩溃。尝试用lodash.debounce包裹该函数后,函数却停止工作了,请问问题出在哪里?如何修复?

原代码片段

resethUserState() {
  this.authService.sessionExtention().subscribe();
  console.log('reset');
}

@HostListener('window:click')
@HostListener('window:mousemove')
@HostListener('window:keydown')
function() {
  debounce(this.resethUserState, 1000);
}

完整组件代码

import { Component, HostListener, OnInit } from '@angular/core';
import { AuthService } from '../../auth.service';
import { Router } from '@angular/router';
import Paths from '../../paths';
import { PushNotificationService } from 'src/app/push-notification.service';
import debounce from 'lodash.debounce';

@Component({
  selector: 'app-lobby',
  templateUrl: './lobby.component.html',
  styleUrls: ['./lobby.component.scss'],
})
export class LobbyComponent implements OnInit {
  constructor(
    private router: Router,
    private authService: AuthService,

    private pushNotificationService: PushNotificationService
  ) {

  }

  ngOnInit(): void {}

  logoutUser() {
    this.authService.logout();
    this.pushNotificationService.createNotification('Logged out!');
    this.router.navigate([`/${Paths.Login}`]);
    return false;
  }


   resetUserState() {
     this.authService.sessionExtention().subscribe();
     console.log('reset');
   }
   
  @HostListener('window:click')
  @HostListener('window:mousemove')
  @HostListener('window:keydown')
   function() {
     debounce(this.resetUserState, 1000);
   }
 
}

问题原因
  1. 防抖函数未执行:你现在只是在事件处理里创建了防抖函数,但没有调用它。debounce(...)返回的是一个新的防抖包装函数,必须执行这个返回值才会触发逻辑。
  2. this指向丢失:直接把this.resetUserState传给debounce时,函数内部的this会脱离组件实例,导致调用this.authService时出错。
  3. 重复创建防抖函数:每次事件触发都会生成全新的防抖函数,这些函数互相独立,根本起不到“防抖”的作用——防抖需要复用同一个函数实例来追踪时间间隔。
修复方案

推荐提前初始化防抖函数实例的方式,这是最规范的做法:

import { Component, HostListener, OnInit, OnDestroy } from '@angular/core';
import { AuthService } from '../../auth.service';
import { Router } from '@angular/router';
import Paths from '../../paths';
import { PushNotificationService } from 'src/app/push-notification.service';
import debounce from 'lodash.debounce';

@Component({
  selector: 'app-lobby',
  templateUrl: './lobby.component.html',
  styleUrls: ['./lobby.component.scss'],
})
export class LobbyComponent implements OnInit, OnDestroy {
  // 提前创建防抖函数实例,用箭头函数绑定当前组件的this
  private debouncedReset = debounce(() => this.resetUserState(), 1000);

  constructor(
    private router: Router,
    private authService: AuthService,
    private pushNotificationService: PushNotificationService
  ) {}

  ngOnInit(): void {}

  // 组件销毁时取消防抖定时器,避免内存泄漏
  ngOnDestroy(): void {
    this.debouncedReset.cancel();
  }

  logoutUser() {
    this.authService.logout();
    this.pushNotificationService.createNotification('Logged out!');
    this.router.navigate([`/${Paths.Login}`]);
    return false;
  }

  resetUserState() {
    this.authService.sessionExtention().subscribe();
    console.log('reset');
  }

  @HostListener('window:click')
  @HostListener('window:mousemove')
  @HostListener('window:keydown')
  onUserActivity() {
    // 调用提前创建好的防抖函数
    this.debouncedReset();
  }
}

临时测试方案(不推荐长期使用)

如果只是临时验证,可以直接在事件处理中调用防抖后的函数,但这种方式每次事件都会创建新的防抖函数,无法复用状态:

@HostListener('window:click')
@HostListener('window:mousemove')
@HostListener('window:keydown')
onUserActivity() {
  debounce(() => this.resetUserState(), 1000)();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 08:30:45