0

我有一个 Angular 7 模板,它提供了book$一个 observabletranslationsAsArray$作为成员的 observable:

<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$就解决了。

你知道原因吗?我的模板应该看起来不同吗?

4

2 回答 2

0

您的 getter 方法get translationsAsArray$()在每次调用时都会返回一个新的 Observable 对象。Angular 的async管道看到一个新的对象引用,所以它订阅了新的 observable。

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 对象引用保持不变。

为此,请将 getter 更改为常规对象属性:

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

如果translationsAsArray$ 必须是getter,则应缓存返回对象,以免每次都返回新的对象引用。

StackBlitz 演示。

于 2019-02-26T15:29:11.240 回答
0

防止这种情况发生的一个技巧是创建一个模板变量对象,将所有可观察对象作为属性,并使用它来控制模板:

<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>
于 2019-02-25T16:18:07.810 回答