Функция SetTimeOut внутри ngOnInit углового компонента при использовании Angular Material DataTable - PullRequest
0 голосов
/ 24 сентября 2018

Я просматривал код 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, указывая, что подписка еще не называется '

4). Это причина, по которой setTimeout вызывается внутри ngOnInit метода?

5) Если это так, то какой метод ngAfterViewInit используется?

Ответы [ 3 ]

0 голосов
/ 24 сентября 2018

Я попытаюсь упростить описание:

  1. setTimeout помещает внутреннюю функцию в конец очереди javascript, поэтому во время выполнения процесса javascript она будет всплывать из стека и вызыватьоперация.все в очереди будет вызываться, только если стек пуст.поэтому setTimeout предписывает javascript хранить этот код до тех пор, пока вы не закончите свою работу.

  2. подписывайтесь и наблюдайте: observable - это асинхронная структура данных, так что как только вы подпишетесь на нее, вы теперь никогда не сможете узнать, сколькоВремя, необходимое для вызова метода подписки.другими словами, подписка будет вызываться только в том случае, если в качестве примера возвращается HTTP-ответ.

Возвращаясь к вашему вопросу: вы не можете знать, когда вызывается ваш код setTimeout, но теоретически он будет вызываться раньшеподписка (движок JavaScript быстрее, чем HTTP-ответ).

Если вам нужно инициализировать некоторую структуру таблицы данных только после того, как вы получите данные из HTTP-запроса, вы должны поместить ее в метод subscribe и не использовать setTimeout..

ngAfterViewInit используется angular, чтобы сообщить разработчику, что на этом этапе ваш view готов, и вы можете в качестве примера использовать elementRef.

ngOnInit используется angularсообщить разработчику, что все входные данные и директивы ... и т. д.

0 голосов
/ 24 сентября 2018

1. нет, setTimeout будет вызываться только один раз и перед подпиской как вне его контекста.

2. из-за асинхронного обновления, если мыобновлять свойства асинхронно, значения не будут обновляться при выполнении цикла проверки, и мы не получим ошибок.

3. ViewChild доступен только после ngAfterViewInit.он заполняет дочерние элементы при создании представления, поэтому они доступны ранее.

4. Хук жизненного цикла ngOnInit запускается перед операцией обновления DOM и не дает ошибок.Хук жизненного цикла ngOnInit запускается после обработки привязок.ngAfterViewInit вызывается, когда представление первоначально отображается, то есть оно вызывается после того, как создается представление компонента и его дочерние представления.

5. ngAfterViewInit () должен вызываться после представления компонента,и его дочерние представления созданы, и, что наиболее важно, детские ngAfterViewInit () вызываются перед родительским ngAfterViewInit ().

0 голосов
/ 24 сентября 2018

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.

Вы можете себе это представить, когда вы гуляете с двумя людьми: один знает английский, а другой нет.Так что даже если вы скажете "Как дела?"сначала парню, который не знает английского, ему понадобится время, чтобы понять, что ты сказал, и ответить тебе.В то же время другой парень (который очень хорошо знает английский) ответит вам мгновенно.

Пример functionA и functionB такой же.Функция A выполняется только , когда подписка что-то ловит.Вот почему он не выстрелил первым.Вы можете видеть, что установка точки отладки здесь:

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);
        }

Какая функция будет выполнена первой?

Спойлер: Вы не можете этого знать.

Если вам интересно, почему, это легко: вы точно знаете, что функция B будет вызываться через 500 мс, но вы не можете знать, скольковремя будет использовать подписку, чтобы быть готовым.Поэтому, если вам повезло, и ваша подписка обычно требует около 500 мс, вы можете попытаться перезагрузить страницу несколько раз, иногда вы увидите Hello, world!, иногда вы увидите world!Hello,.

Чтобы ответитьлучше на ваши вопросы: я действительно не знаю, почему вы поместили код, как это, буквально понятия не имею.

ngAfterViewInit представляет собой life-cycle с именем после ngOnInitи выполните логику после того, как Angular полностью инициализирует представление компонента.

...