#typescript #rxjs #nestjs
#typescript #rxjs #nestjs
Вопрос:
У меня есть конвейер RXJS, похожий на этот:
const logs: number[] = [1, 2, 3, 4];
const url = 'http://some-url-here.com';
const pipeline = from(logs).pipe(
switchMap(logId =>
this.callEndpoint(url, logId).pipe(map(response => response.data)),
),
);
const res = await pipeline.toPromise();
console.log(res);
// The real function uses nestJS http service to call a url
callEndpoint(url: string, logId: number) {
const result = Math.random() * 1000;
console.log(`result in callEndpoint: ${result}`);
return of({ data: result });
}
вот пример вывода кода:
result in callEndpoint: 586.773956063481
result in callEndpoint: 842.136341622411
result in callEndpoint: 964.0849490798163
result in callEndpoint: 598.7596176858414
598.7596176858414
Последнее число является результатом res
.
Как мне получить объединенные результаты всех успешных вызовов конечных точек в один массив res
?
Ответ №1:
Используйте forkJoin
, если вы хотите отправить все запросы сразу или concat
с toArray
, чтобы отправлять запросы последовательно и собирать результаты в массив. Вероятно, вы захотите добавить обработку ошибок catchError
и вернуть наблюдаемое значение, которое в этом случае не вызывает ошибок.
const getData = (logId) => this.callEndpoint(url, logId).pipe(
map(response => response.data),
catchError(error => of(null))
)
const requests = logs.map(logId => getData(logId));
// parallel requests
forkJoin(requests).subscribe(res => console.log(res));
// sequential requests
concat(...requests).pipe(toArray()).subscribe(res => console.log(res));
res
будет представлять собой массив, который может содержать null
значения в случае сбоя запроса.
При сбое второго запроса это может выглядеть так:
[586.773956063481, null, 964.0849490798163, 598.7596176858414]
Ответ №2:
Вы можете использовать toArray()
для сбора всех выбросов и выделения их в виде одного массива после завершения исходной наблюдаемой.
const pipeline = from(logs).pipe(
switchMap(logId =>
this.callEndpoint(url, logId).pipe(map(response => response.data)),
),
toArray(),
);
Тем не менее, я думаю, что вы не хотите использовать switchMap
в этом случае, потому что наблюдаемый здесь источник from()
— это то, что сразу же отправит все элементы logs
и switchMap
сохранит подписку только на последний. Поэтому вы можете использовать concatMap
вместо этого.