Наблюдаемый, имеющий наблюдаемый член в шаблоне - PullRequest
0 голосов
/ 25 февраля 2019

У меня есть шаблон Angular 7, который представляет наблюдаемую book$ с наблюдаемой translationsAsArray$ в качестве члена:

<div *ngIf="book$ | async as book">
  <dl>
    <div *ngIf="(book.translationsAsArray$ | async) as translations">
      <dt><b class="text-muted">TRANSLATIONS</b></dt>
      <dd>
        <ul class="list-unstyled">
          <li *ngFor="let translation of translations">
            <a routerLink="/books/{{translation.rid}}">{{translation.title}}</a> ({{translation.languageAsString}})
          </li>
        </ul>
      </dd>
    </div>
  </dl>
</div>

Редактировать: book.translationsAsArray$ выглядит следующим образом (только для целей тестирования):

get translationsAsArray$(): Observable<Book[]> {
    return timer(50).pipe(
        tap(time => console.log('translationsAsArray$() subsribed')),
        map(time => [new Book(this.bookService, 'abc')]));
}

Проблема, с которой я сталкиваюсь, заключается в том, что translationsAsArray$ повторно подписывается повторно.

Когда я изменяю решение на вызов subscribe вмашинописный текст вместо использования async трубы для book$ и translationsAsArray$ проблема решена.

Знаете ли вы причину?Должен ли мой шаблон выглядеть иначе?

Ответы [ 2 ]

0 голосов
/ 26 февраля 2019

Ваш метод получения get translationsAsArray$() возвращает новый объект Observable каждый раз, когда он вызывается.Канал Angular async видит новую ссылку на объект, поэтому он подписывается на новую наблюдаемую.

get observableObj() {
  // Returns a new object each time
  return timer(50);
}

constructor() {
  console.log('Testing Observable reference equality');
  const obj1 = this.observableObj;
  const obj2 = this.observableObj;
  console.log('Different Object references?', obj1 !== obj2); // true
}

Вы должны убедиться, что ссылка на наблюдаемый объект остается прежней.

Для этогозамените метод получения на свойство обычного объекта:

book.translationsAsArray$ = timer(50).pipe(
  tap(time => console.log('translationsAsArray subscribed')),
  map(time => ['abc'])
)

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

Демонстрация StackBlitz.

0 голосов
/ 25 февраля 2019

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

<div *ngIf="{ book: (book$ | async), translations: (term.translationsAsArray$ | async) } as asyncs"
  <div *ngIf="asyncs.book">
    <dl>
      <div *ngIf="asyncs.translations">
        <dt><b class="text-muted">TRANSLATIONS</b></dt>
        <dd>
          <ul class="list-unstyled">
            <li *ngFor="let translation of asyncs.translations">
              <a routerLink="/books/{{translation.rid}}">{{translation.title}}</a> ({{translation.languageAsString}})
            </li>
          </ul>
        </dd>
      </div>
    </dl>
  </div>
</div>
...