Угловой цикл над итератором

#angular #typescript #iterator #yield

#угловой #typescript #итератор #выход

Вопрос:

У меня есть компонент с методом:

 public *numGen(): Iterator<number> {
    for (let i = 0; i < 5;   i)
      yield i;
  }
  

и HTML с:

 <p *ngFor="let n of numGen()">{{n}}</p>
  

Я ожидаю, что это сгенерирует:

 <p>0</p>
<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>
  

что он и делает, но при этом также генерируется ошибка:

 ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. 
Previous value: 'ngForOf: [object Generator]'. Current value: 'ngForOf: [object Generator]'.
  

Кто-нибудь знает, как предотвратить генерирование ошибки?

Ответ №1:

Один из способов — использовать OnPush стратегию обнаружения изменений. Это гарантирует, что он проверяет привязки только тогда, когда что-то внутри компонента изменилось с помощью @Input или события, отправленного из шаблона. Который сам по себе имеет значительное улучшение производительности и более логичную схему срабатывания обнаружения изменений.

 @Component({
  // ...
  changeDetection: ChangeDetectionStrategy.OnPush
})
  

смотрите здесь

Причина, по которой вы видите эту ошибку, заключается в том, что ваш метод возвращает новую Generator ссылку на объект при каждом обнаружении изменения.


Другим способом было бы устанавливать генератор только тогда, когда в вашем компоненте что-то меняется, что требует обновления генератора. Для этого вы могли бы использовать ngDoCheck крючок. Имейте в виду, что это происходит довольно часто, хотя и не так часто, если вы используете OnPush стратегию, которую я в любом случае настоятельно рекомендую.

 export class AppComponent  {
  generator: Iterable<number> = this.numGen();

  multiplier = 1;

  ngDoCheck(): void {
    this.generator = this.numGen();
  }

  times(): void {
    this.multiplier *= 2;
  }

  private *numGen(): Iterable<number> {
    for (let i = 0; i < 5;   i) {     
      yield i * this.multiplier;
    }
  }
}
  

пример с ngDoCheck

Мне действительно интересно, для какого варианта использования вы используете итератор / генератор?

Комментарии:

1. Ах! Я думал, что попробовал что-то похожее на подход ngOnChanges. Стратегия ChangeDetectionStrategy отлично работает.

2. Я не совсем уверен, нужно ли мне это использовать, но я просто экспериментировал, чтобы посмотреть, сработает ли это. В конечном итоге у меня есть 2D-массив, который я хотел бы иметь возможность просматривать иногда как набор столбцов, а иногда как набор строк. Использование итератора кажется проще, чем копирование содержимого в массивы для столбцов. Я должен отметить, что я думаю как программист C #.

3. @JasperKent Хорошо, тогда это имеет смысл 🙂 генераторы обычно не являются моим первым решением, просто когда производительность становится проблемой при работе с большими наборами данных, так что, возможно, вы имеете в виду правильный вариант использования!

4. @JasperKent Я немного обновил свой ответ, предложив решение для ngOnChanges 🙂 (подождите, это, очевидно, не работает, игнорируйте это)

5. @JasperKent хорошо: p теперь я нашел другой способ