angular - setTimeOut() 在 Angular Lifecycle Hooks : ngDoCheck, ngAfterContentChecked, ngAfterViewChecked 中重复

标签 angular settimeout

再现性

我有一个小的 TypeScript 代码片段,如下所示:

ngAfterViewChecked(){
    console.log("ngAfterViewChecked 1");
    setTimeout(() => {
      console.log("ngAfterViewChecked 2");
    }, 1000);
  }

功能 setTimeOut()应该在 1 秒后调用 lambda 函数然后停止。然而,钩子(Hook) ngAfterViewChecked() 被连续调用(摘自 Chrome 开发者工具控制台):
00:36:50.827 home.component.ts:53 ngAfterViewChecked 1
00:36:51.842 home.component.ts:55 ngAfterViewChecked 2
00:36:51.843 home.component.ts:53 ngAfterViewChecked 1
00:36:52.843 home.component.ts:55 ngAfterViewChecked 2
00:36:52.844 home.component.ts:53 ngAfterViewChecked 1
00:36:53.845 home.component.ts:55 ngAfterViewChecked 2
00:36:53.846 home.component.ts:53 ngAfterViewChecked 1
00:36:54.848 home.component.ts:55 ngAfterViewChecked 2
...

没有 setTimeOut() , 功能 ngAfterViewChecked()被调用一次。 ngDoCheck() 也会出现此问题, ngAfterContentChecked() .

使用其他 Angular 生命周期钩子(Hook)进行测试

相同的代码体,有或没有 setTimeOut() , 在 constructor() 中声明, ngOnInit() , ngAfterContentInit() , ngAfterViewInit() ,按预期被调用一次。

环境
  • 该程序非常简单(例如 Angular 的“Hello World”)。没有第 3 方库。
  • Angular 5 和 6 都有这个问题(较低版本尚未经过测试)。它们分别安装在不同的机器上。
    Angular CLI: 6.0.8
    Node: 8.11.3
    OS: win32 x64
    Angular: 6.0.9
    
    
    Angular CLI: 1.7.4
    Node: 8.11.1
    OS: win32 x64
    Angular: 5.2.10
    
  • window 8.1 x64。
  • 谷歌浏览器 67(64 位)。

  • 我猜

    Hook constructor() , ngOnInit() , ngAfterContentInit() , ngAfterViewInit()在组件的整个生命周期中调用一次,无论其内容在其生命周期中如何演变。所以这个问题合理地不会在这些钩子(Hook)中发生。

    ngDoCheck() , ngAfterContentChecked()ngAfterViewChecked() ,当 Angular 检测到更改时,它们会被调用。但正如 lambda 函数体所示,只有简单的 console.log()用来。我认为 Angular 可能会拦截 setTimeOut()调用并盲目地认为可能发生了一些变化,因此它启动了更改检测过程,这导致了我们所看到的:调用无限链接。

    问题

    这是错误还是功能?

    最佳答案

    功能 - Angular 的更改检测在异步操作完成后运行(如 setTimeout) - 所以 setTimeout 本身会导致 ngAfterViewChecked运行,反之亦然。

    如果您不希望这种情况发生,您可以在 Angular 的区域之外运行,即

       ngAfterViewChecked(){
        console.log("ngAfterViewChecked 1");
    
        this.ngZone.runOutsideAngular(() => {
          setTimeout(() => {
            console.log("ngAfterViewChecked 2");
          }, 1000);
        });
      }
    

    您可以在构造函数中注入(inject) NgZone,即 private ngZone: NgZone .查看 Angular 和 zone.js 之间的关系以获取更多信息。

    关于angular - setTimeOut() 在 Angular Lifecycle Hooks : ngDoCheck, ngAfterContentChecked, ngAfterViewChecked 中重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51333858/

    相关文章:

    javascript - 使用 setTimeout 推迟数据输入时的时间密集型处理

    javascript - 无法理解 `setTimeout()` 中的最小超时值

    javascript - 顺序调用javascript代码的替代方法,中间有延迟

    angular - Ionic3/Angular 错误 : Must supply a value for form control with name: 'jobStatus'

    javascript - Angular 4 : Refresh data in a div

    javascript - javascript中第一个函数中的setTimeout()和第二个函数中的闭包是否会出现堆栈溢出错误?

    javascript - useState 不更新其值

    angular - 从 Angular 2 中的 config.json 获取数据

    angular - 禁用浏览器中的图像缓存

    angular - 在远程服务器中 Dockerize Angular cli 应用程序