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

Life Cycle DoCheck in Angular 2 getting executed Infinitely

我制作了一个基于 MEAN 堆栈的小型应用程序,并在组件生命周期内使用了一个服务方法。每当值发生变化时,我都使用 DoCheck 生命周期从服务器获取新值。我虽然生命周期将在值更改时或以固定间隔执行。 但是 DoCheck 生命周期挂钩正在无限执行并向服务器发送无限请求。

组件截图如下:

export class CommentsComponent implements DoCheck {

    comments: Comment[] = [];

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

}

我期望的是生命周期挂钩会向服务器发送请求以获取新评论(其他用户可能 posted),只要他们实际 post 或以固定的时间间隔,但是生命周期挂钩无限发送请求。 (抱歉,来自 Chrome 开发人员工具的屏幕截图,我的 PC 在加载应用程序后立即冻结)。

服务代码如下:

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

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

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

根据 documentaionngDoCheck

Called immediately after ngOnChanges() on every change detection run, and immediately after ngOnInit() on the first run

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

来自documentation

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

  • 组件初始化。例如,当 bootstrapping 一个 Angular 应用程序时,Angular 加载 bootstrap 组件并触发 ApplicationRef.tick() 调用变化检测和视图渲染。

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

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

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

  • 微任务,例如Promise.then()。其他异步APIreturn一个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));
    })
  }

}