Angular 2中的生命周期DoCheck无限执行

时间:2017-09-17 13:35:02

标签: angular mean-stack lifecycle

我做了一个基于MEAN堆栈的小应用程序,并在组件生命周期内使用了一个服务方法。每当值发生变化时,我都使用DoCheck生命周期从服务器获取新值。我虽然每当值发生变化时都会执行生命周期,或者以固定的间隔执行。 但DoCheck Life循环钩子无限执行并向服务器发送无限请求。

组件截图如下:

export class CommentsComponent implements DoCheck {

    comments: Comment[] = [];

    ngDoCheck() {
        this.commentService.getComments().subscribe((result) => {
            this.comments = result.comments;
        }, (error) => console.log(error));
    }

}

我所期望的是生命周期钩子会向服务器发送请求以获取新注释(其他用户可能已发布),无论何时实际发布或以固定间隔发送,但生命周期钩子无限地发送请求。 (对不起Chrome Developer工具的截图,我的PC在加载应用程序后立即冻结。)

服务代码如下:

export class CommentService {
  getComments () {
    return this.http.get('http://www.localhost:3000/getcomment').map(res => res.json());
  }
}

PS:我的应用程序在端口4200上运行,而我的后端在端口3000上运行 完整的应用程序存储库为here

如果我使用OnInit生命周期钩子,那么一旦组件生成就会发出请求,虽然它不是我想要的,但它表明服务的服务/使用没有错误(编码不正确),生命周期hook正在发送请求。

1 个答案:

答案 0 :(得分:1)

根据documentaionngDoCheck

<块引用>

在每次更改检测运行时立即在 ngOnChanges() 之后调用, 并在第一次运行时立即在 ngOnInit() 之后

请注意,angular 还使用 NgZone 来确定 html 是否会更新

来自documentation

要了解更改检测的工作原理,首先要考虑应用程序何时需要更新 HTML。通常,更新是出于以下原因之一:

  • 组件初始化。例如,在引导 Angular 应用程序时,Angular 会加载引导程序组件并触发 ApplicationRef.tick() 以调用更改检测和视图渲染。

  • 事件监听器。 DOM 事件侦听器可以更新 Angular 组件中的数据,也可以触发更改检测,如下例所示。

  • HTTP 数据请求。您还可以通过 HTTP 请求从服务器获取数据。

  • 宏任务,例如 setTimeout() 或 setInterval()。也可以在宏任务的回调函数中更新数据,例如setTimeout()。

  • 微任务,例如 Promise.then()。其他异步API返回一个Promise对象(如fetch),因此then()回调函数也可以更新数据。

  • 其他异步操作。除了 addEventListener()、setTimeout() 和 Promise.then() 之外,还有其他操作可以异步更新数据。一些示例包括 WebSocket.onmessage() 和 Canvas.toBlob()。

在此事件之后,Angular 再次运行更改检测以检测数据可能已更改。

因此,在您的代码中,您正在制作 Http request,之后 Angular 再次运行检测以检查数据是否已更改并再次调用 ngDoCheck。在 ngDoCheck 中,您再次发出 http 请求。这就是为什么你会得到无限循环。

现在要从您的服务器获取 commnet,您可以创建 rxjs interval

import { interval } from 'rxjs';
----
export class Appcomponent {
  ngOninit() {
    interval(3000).subscribe(x => {
      this.commentService.getComments().subscribe((result) => {
        this.comments = result.comments;
      }, (error) => console.log(error));
    })
  }

}