У меня есть API, который возвращает мне Array<string> идентификаторов с учетом исходного идентификатора (один ко многим). Мне нужно сделать http-запрос для каждого из этих идентификаторов, чтобы получить связанные данные из API. Я не могу понять, как взять Observable<string[]> и сопоставить его с Observable<DataType[]>.
Я хотел бы сохранить оригинал наблюдаемым и использовать операторы для получения желаемого результата, если это вообще возможно.
Конвейерная передача оператора map в этой ситуации не работает из-за того, что единственным элементом в наблюдаемом объекте является массив.
Вот пример кода, который похож на реализацию, которую я пытаюсь реализовать.
getIds = (originalId: string) => {
return this.http.get<string[]>(url);
}
getDataFromIds = (originalId: string): Observable<DataType[]> => {
const ids$ = this.getIds(originalId);
// Make http calls for each of the items in the array.
result = ids$.pipe();
return result;
}
Хорошая точка зрения. Я не думал о возможности сбоя http. Если запрос не выполнен, он должен просто перейти к следующему идентификатору, исключая неудачный ответ.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы можете попробовать это:
ids$.pipe(
switchMap(ids => //you can swap switchMap with any *Map operator: https://www.learnrxjs.io/operators/transformation/
forkJoin(...ids.map(id => //you swap forkJoin with any comb. operator: https://www.learnrxjs.io/operators/combination/
from(Promise.resolve({ id })).pipe(
map(res => res.id),
catchError(err => of(err)))))));
Импорт для from, forkJoin должен быть из rxjs, а все остальное импортируется из rxjs/operators
catchError будет ловить любые выброшенные ошибки необработанный.
Демо: https://stackblitz.com/edit/rxjs-xmmhyj
это плохой вариант использования zip, поскольку это не завершающий наблюдаемый объект, и обычно в этом случае вы хотите использовать завершающий наблюдаемый объект (forkJoin), чтобы избежать утечек памяти. использование zip может потребовать ненужной очистки подписки
У forkJoin есть недостаток, который требует завершения наблюдаемого для распространения конечного результата, это может заблокировать поток, и вам действительно следует учитывать компромиссы при использовании различных операторов. Каждый случай индивидуален.
OP указал, что речь идет о http-вызовах, что означает, что они завершаются, и forkJoin является правильным оператором для этого варианта использования.
это вариант использования оператора switchMap, как правило, с оператором forkjoin в качестве вашего внутреннего наблюдаемого.
getIds = (originalId: string) => {
return this.http.get<string[]>(url);
}
getDataFromIds = (originalId: string): Observable<DataType[]> => {
const ids$ = this.getIds(originalId);
// Make http calls for each of the items in the array.
result = ids$.pipe(switchmap(ids => forkJoin(ids.map(id => this.getId(id))));
// map the array of ids into an array of Observable<DataType>, forkjoin them and switch into it.
return result;
}
Это предполагает, что вызов getIds() приведет к списку идентификаторов строк и что у вас есть некоторая функция getId(), которая принимает идентификатор строки и возвращает наблюдаемый тип данных.
Мы закончили с тем же результатом, за исключением того, что я использовал оператор combineAll(). Есть ли у моего метода недостатки перед forkJoin()?
В итоге получается то же самое в этом случае использования. Тонкая разница в том, что forkJoin будет выдавать только 1 значение: окончательный массив результатов после завершения всех внутренних наблюдаемых. combineAll может выдавать несколько значений: один раз, когда каждая из внутренних наблюдаемых производит значение, и снова, когда любая из внутренних наблюдаемых создает дополнительное значение. Поскольку ваши внутренние наблюдаемые объекты заканчиваются после 1 значения, это различие становится спорным. Я бы использовал forkJoin, потому что это кажется более семантически правильным.
Тот же результат здесь. Предпочла бы forkJoin, потому что обычно от combLatest ожидается, что внутренние потоки имеют несколько выбросов, тогда как forkJoin является декларативным, что вы ожидаете одиночный выброс.
Грубо говоря, вы хотите сменить карту на forkJoin. Однако вы не описали, что должно произойти в случае сбоя одного из этих запросов.