#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}))))) ));