Наблюдаемый, имеющий наблюдаемый член в шаблоне
У меня есть шаблон 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 ответа
Чтобы избежать этого, нужно создать объект переменной шаблона со всеми наблюдаемыми в качестве свойств и использовать его для управления шаблоном:
<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>
Ваш метод получения get translationsAsArray$()
возвращает новый объект Observable каждый раз, когда он вызывается. Радиально-х async
pipe видит новую ссылку на объект, поэтому он подписывается на новую наблюдаемую.
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
}
Вы должны убедиться, что ваша ссылка на Observable объект остается прежней.
Для этого измените метод get на обычное свойство объекта:
book.translationsAsArray$ = timer(50).pipe(
tap(time => console.log('translationsAsArray subscribed')),
map(time => ['abc'])
)
Если translationsAsArray$
должен быть получателем, вы должны кэшировать возвращаемый объект, чтобы вы не возвращали новую ссылку на объект каждый раз.