Угловой вложенный код подписки работает не так, как ожидалось

#html #angular #asynchronous #publish-subscribe

#HTML #угловой #асинхронный #опубликовать-подписаться

Вопрос:

Моя задача состоит из 2 шагов. Первым шагом является получение некоторых идентификационных данных из firestore. Во-вторых, необходимо получить данные имени на основе данных, полученных на первом шаге. Поэтому я использовал 1 подписку для каждого шага. В коде, в котором я выполняю console.log(), появляется правильный результат, однако при загрузке веб-страницы выпадающий список пуст.

 this.MessagingService.recieveGetClient().subscribe(idData => {
  this.dropdownList = [];
  idData.map((id: string, i: number) => {
    this.VehicleService.getOwnerInfo(id).subscribe(namedata => {
      this.dropdownList.push({ item_id: `${i}`, doc_id: namedata['username'] });
      console.log("this.dropdownList:",this.dropdownList);
    });
  });
});
  

Ниже приведен HTML-код. Если я избавлюсь от второй подписки и использую id вместо имени пользователя для выпадающего списка, тогда это сработает. Но мне нужно использовать имя пользователя.

 <ng-multiselect-dropdown
    [settings]="dropdownSettings"
    [placeholder]="'Send Message to...'"
    [data]="dropdownList"
    [(ngModel)]="selectedItems"
    (onSelect)="onItemSelect()"
    (onSelectAll)="onSelectAll($event)"
    (onDeSelect)="onItemDeSelect()"
    (onDeSelectAll)="onDeSelectAll()"
>
</ng-multiselect-dropdown>
  

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

1. Это кажется хорошим кандидатом для использования switchMap

Ответ №1:

Поскольку это несколько подписок и сопоставление данных, лучше всего использовать observable для передачи разных источников с помощью switchMap, например:

 this.dropdownList$  = this.MessagingService.receiveGetClient()
.pipe(switchMap(id => this.VehicleService.getOwnerInfo(id).pipe(map(nameData => ({id, doc_id: nameData.username})))
));
  

В шаблоне вы можете использовать асинхронный канал для развертывания значения

 [data]="dropdownList$ | async"
  

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

Надеюсь, это поможет!

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

1. Большое спасибо. Однако есть одна сложность. В «»»это. VehicleService.getOwnerInfo(id)»»» идентификатор представляет собой список строк, но getOwnerInfo() принимает строку в качестве аргумента. Я пытаюсь использовать map для обработки строк по отдельности, но, к сожалению, это не работает. Не могли бы вы мне помочь.

2. Я вижу… Я думаю, что тогда вам нужно будет сделать что-то вроде: switchMap(ids => zip(ids.map(id => this.VehicleService.getOwnerInfo(id) . Ознакомьтесь с операторами объединения rxjs, чтобы справиться с ожиданием нескольких асинхронных вызовов — learnrxjs.io/learn-rxjs/operators/combination/zip . Надеюсь, это поможет

3. Я поставил быстрый stackblitz, делающий это в rxjs — stackblitz.com/edit/rxjs-gpshqm const выпадающий список$ = receiveGetClient() .pipe(switchMap(ids => zip(ids.map(id => getOwnerInfo(id).pipe(карта(nameData => ({id, doc_id: nameData.username}))))) ));