* ng Если с асинхронным конвейером для наблюдаемого из BehaviorSubject кажется, что активируется неправильно, пока данные не будут загружены

Если массив в ответ пуст, я хочу отобразить сообщение, в противном случае элементы массива.

Если в ответе есть непустой массив, условие * ngIf принимает значение истина, и сообщение отображается до загрузки данных.

Фрагмент шаблона HTML:

<div *ngIf="personalAndStarredBookmarks$ && (personalAndStarredBookmarks$ | async)?.size === 0; else personalBookmarksList" class="missing-category-bookmarks-message  alert alert-info">
  <p>No bookmarks yet</p>
</div>
<ng-template #personalBookmarksList>
  <app-async-bookmark-list [bookmarks]="personalAndStarredBookmarks$" [shownSize]="10" [userData]="userData"></app-async-bookmark-list>
</ng-template>

Фрагмент компонента:

import { List } from 'immutable';

export class PersonalBookmarksListComponent implements OnInit {

  personalAndStarredBookmarks$: Observable<List<Bookmark>>;

  ngOnInit(): void {

    this.personalAndStarredBookmarks$ = this.personalBookmarksStore.getPersonalBookmarks();
  }
  ...
}

Хранилище использует BehaviourSubject, где хранит ответ от службы, которая фактически выполняет HTTP-вызов.

Фрагмент магазина

@Injectable()
export class PersonalBookmarksStore {

  private _personalBookmarks: BehaviorSubject<List<Bookmark>> = new BehaviorSubject(List([]));

  constructor(private personalBookmarkService: PersonalBookmarkService,
              private keycloakService: KeycloakService
  ) {
    keycloakService.loadUserProfile().then(keycloakProfile => {
      this.userId = keycloakProfile.id;
      this.loadInitialData();
    });
  }

  private loadInitialData() {
    this.personalBookmarkService.getAllPersonalBookmarks(this.userId)
      .subscribe(
        data => {
          let bookmarks: Bookmark[] = <Bookmark[]>data;
          this._personalBookmarks.next(List(bookmarks));
        },
        err => console.error('Error retrieving bookmarks', err)
      );
  }

  getPersonalBookmarks(): Observable<List<Bookmark>> {
    return this._personalBookmarks.asObservable();
  }
  ...
}

Если я вызываю непосредственно Службу (а не Магазин) в компоненте, она ведет себя так, как ожидалось ...


person ama    schedule 21.04.2019    source источник
comment
Я думаю, вы намеревались написать в своем шаблоне .length, а не .size.   -  person AryanJ-NYC    schedule 21.04.2019


Ответы (2)


Причина - инициализация BehaviorSubject с помощью пустого списка, который генерируется, и условие оценивается как истинное:

private _personalBookmarks: BehaviorSubject<List<Bookmark>> = new BehaviorSubject(List([]));

Исправить - инициализировать BehaviorSubject с null или undefined

private _personalBookmarks: BehaviorSubject<List<Bookmark>> = new BehaviorSubject(null);
person ama    schedule 22.04.2019

Вам следует реструктурировать свой шаблон, чтобы эффективно обрабатывать асинхронные вызовы, назначив локальную переменную как

<ng-content*ngIf="personalAndStarredBookmarks$ | async as personalAndStarredBookmarks">
    <div *ngIf="personalAndStarredBookmarks.size === 0; else personalBookmarksList" 
        class="missing-category-bookmarks-message  alert alert-info">
        <p>No bookmarks yet</p>
    </div>
    <ng-template #personalBookmarksList>
        <app-async-bookmark-list [bookmarks]="personalAndStarredBookmarks" [shownSize]="10"
            [userData]="userData">
        </app-async-bookmark-list>
    </ng-template>
<ng-content>

Благодаря этому вы можете эффективно обрабатывать все условия, а основное содержимое загружается только после разрешения асинхронного вызова.

См. ДЕМО ЗДЕСЬ

person Saksham    schedule 21.04.2019
comment
Спасибо, я обновил вопрос для ясности, но это должно быть обнаружено с помощью оператора безопасности (?) И должно оцениваться как false, верно? ... см. angular.io/guide/template-syntax#safe-navigation-operator - person ama; 22.04.2019
comment
@Adrian, вам не нужно изначально назначать свой BehaviorSubject null и следовать подходу, который я опубликовал. Дай мне знать, если ты думаешь иначе. - person Saksham; 22.04.2019
comment
Привет @Saksham, да, виноват был пустой массив при инициализации BehaviorSubject. Я понял это, прежде чем извиниться, посмотреть мой ответ и решение ... - person ama; 22.04.2019
comment
@Adrian: да, я видел ваше решение, но тот, который я реализовал выше, обеспечивает более эффективную доступность с меньшим количеством сравнений. - person Saksham; 22.04.2019
comment
Я не понимаю, насколько он более производительный по сравнению с (personalAndStarredBookmarks$ | async)?.size === 0, который ожидает завершения асинхронной операции и выполняет сравнение ... Это правда, что вам не нужно использовать асинхронный конвейер по строке, но в этой ситуации код более многословно .... У вас есть ссылка? - person ama; 22.04.2019