使用Angular Material DataTable时Angular组件ngOnInit内的SetTimeOut函数

时间:2018-09-24 12:15:25

标签: javascript angular angular-material settimeout

我正在一个现有项目中浏览Angular代码,并在以下代码段中找到。 我们正在使用Angular material datatable在页面上呈现视图

export class Component implements OnInit,AfterViewInit{

  private dataSource: MatTableDataSource<Product> = null;
  @ViewChild(MatPaginator) paginator: MatPaginator; 

  columnsToDisplay = ['productId','productname'];
  constructor(private _service : DataService) { }

  ngOnInit() {

    this._service.getProducts().subscribe(
     ((data : Product[]) => this.dataSource = new MatTableDataSource(data)),
     () => console.log('THIS IS ERROR')
    );
    setTimeout(() => this.dataSource.paginator = this.paginator);
    //this.dataSource.paginator = this.paginator;
  }

  ngAfterViewInit() {
    this.dataSource.paginator = this.paginator; 
  }

}

我的问题是:

1)由于this.service.getData()返回一个Observable,并且只要subscribe可用,HttpResponse就会被异步调用,      setTimeout函数内部的操作是否将被称为仅在之后?subscribe方法被调用?

2)我已经看到ngAfterViewInit方法还包含与setTimeout方法中的ngOnInit方法相同的代码

3)但是,当此方法称为(ngAfterViewInit)时,this.products仍然为NULL,表示尚未将subscribe称为'

4)是在setTimeout方法内部调用ngOnInit的原因吗?

5)如果是这种情况,ngAfterViewInit方法的用途是什么?

3 个答案:

答案 0 :(得分:1)

1)这取决于。订阅仅在操作完成后才执行代码。因此,this.service.getData()完成工作后。 setTimeout在延迟后执行该工作。如果订阅所需的时间少于setTimeout,则将首先执行。

2)也许您正试图注意到函数执行的时间?

3)AfterViewInit被多次触发。您可以像这样if(!!something)进行检查,然后执行一些代码。

4)您应该始终避免使用settimeout(仅将其用于调试目的)。

编辑:

ngOnInit(){

this._service.getProducts().subscribe(
 ((data : Product[]) => this.dataSource = new MatTableDataSource(data)),
 () => console.log('THIS IS ERROR')
);
setTimeout(() => this.dataSource.paginator = this.paginator);
//this.dataSource.paginator = this.paginator;

} `

让我们简单地讲一下这段代码:

ngOnInit() {
  this.service.doStuff()
  .subscribe(result => {
    this.functionA();
  },
  err => {
    //Do other stuff in case of an error
  });

  this.functionB();
}

functionA(){
  console.log("Hello,");
}

functionB(){
  console.log("world!");
}

此代码的输出将是:

world!Hello,

但是为什么?

那是因为observable模式。

您可以想象,当您与两个人同行时:一个会英语,另一个不会。因此,即使您说“你好吗?”首先是一个不懂英语的人,他将需要时间来理解你说的话并回答你。同时,另一个人(非常懂英语)会立即回答您。

functionAfunctionB的示例相同。订阅已捕获某些内容时,仅执行功能。这就是为什么不首先触发它的原因。您可以看到在此处放置调试点:

ngOnInit() {
      this.service.doStuff()
      .subscribe(result => {
      --->  this.functionA();
      },
      err => {
        //Do other stuff in case of an error
      });

      --->  this.functionB();
    }

希望对此进行很好的解释。

现在让我们继续,让我们使用超时时间:

 ngOnInit() {
          this.service.doStuff()
          .subscribe(result => {
            this.functionA();
          },
          err => {
            //Do other stuff in case of an error
          });

          settimeout(() => {
            this.functionB();
          }, 500);
        }

哪个功能将首先执行?

剧透:你不知道。

如果您想知道为什么,这很容易:您完全知道functionB将在500ms之后被调用,但是您不知道将使用预订准备多少时间。因此,如果幸运的话,您的订阅通常需要大约500毫秒才能完成,因此您可以尝试重新加载页面几次,有时会看到Hello, world!,有时会看到world!Hello,

为了更好地回答您的问题:我真的不知道您为什么要像这样放置代码,实际上不知道。

ngAfterViewInit是一个life-cycle,位于ngOnInit之后,称为,在Angular完全初始化组件的视图之后执行该逻辑。

答案 1 :(得分:1)

我将尝试简化描述:

  1. setTimeout将内部函数放在javascript队列的末尾,因此当javascript进程运行时,它将从堆栈中弹出并调用该操作。仅当堆栈为空时,队列中的所有内容才会被调用。因此setTimeout告诉javascript保留这段代码,直到完成工作为止。

  2. 可订阅和可观察:可观察是异步数据结构,因此一旦订阅它,您将永远无法花费多少时间来调用subscribe方法。换句话说,只有在http响应返回的情况下,subscribe才会被调用。

回到您的问题:您不知道何时调用setTimeout代码,但从理论上讲,它将在订阅之前被调用(JavaScript引擎比http响应速度更快)。

如果仅在从http请求中获取数据后才需要初始化某些数据表结构,则应将其放入subscribe方法中,而无需setTimeout。

ngAfterViewInit用于通知开发人员在此阶段您的view已准备就绪,您可以使用elementRef作为示例。

ngOnInit用来表示开发人员所有输入和指令...等。

答案 2 :(得分:0)

1。否,setTimeout将仅被调用一次,然后在其上下文之外进行订阅。

2。。由于异步更新,如果我们异步更新属性,则在验证循环运行时不会更新值,并且不会出错。

3。。只有在ngAfterViewInit之后,ViewChild才可用。它会在创建视图时填充子级,因此可以更早使用它们。

4。。ngOnInit生命周期挂钩在DOM更新操作之前被触发,不会产生任何错误。处理绑定后,将触发ngOnInit生命周期挂钩。最初呈现视图时即调用ngAfterViewInit,即在创建组件的视图及其子视图之后调用。

5。。应在组件的视图及其子视图创建之后调用ngAfterViewInit(),最重要的是,在父级的ngAfterViewInit()之前调用子项的ngAfterViewInit()。