#javascript #asynchronous #callback #rxjs #nested
#javascript #асинхронный #обратный вызов #rxjs #вложенный
Вопрос:
Как лучше всего мы можем сгладить приведенные ниже вызовы. Новичок в RxJS, пытаюсь понять, как его следует упростить. Прочитайте flatMap, forkJoin, switchMap и mergeMap, не получив правильного пути для его интеграции ниже и не уверен, что лучше в приведенном ниже сценарии.
const useful = [];
a.get('abc').
subscribe((abcdatas) => {
abcdatas.forEach(abcdata => {
if(abcdata.exist) {
b.get('def').
subscribe((defdatas) => {
useful.push(defdatas.someval);
});
}
});
})
if(useful.length) {
c.get('ghi').
subscribe((ghidata) => {
completed...
});
}
Обновить
Обновляю свой вопрос здесь и благодарю за все ответы. Полезным является глобальный массив результатов, который в моем случае должен быть заполнен из вложенного вызова. И, наконец, он должен быть передан последнему вызову.
Шаги, которые я пытаюсь:
- a.get() => возвращает adata
- b.get(adataset) => должен выполнить запрос для каждого adataset, если adataset имеет атрибут exist, а также заполнить полезный массив, который будет использоваться позже
- c.get(полезный) => должен сработать и завершиться.
Ответ №1:
Используйте функцию сопоставления, например switchMap
or mergeMap
, для сопоставления результата от одного запроса к следующему запросу. Используется forkJoin
для одновременного выполнения нескольких запросов.
Итак, для сценария «один ко многим» общая идея такова:
firstRequest().pipe(
switchMap(results => forkJoin(results.map(r => nextRequest(r))))
)
Для вашего случая это было бы что-то вроде:
useful = [];
a.get('abc').pipe(
switchMap(abcdatas => forkJoin(getUseFulRequests(abcdatas))),
tap(useful => useful.forEach(u => this.useful.push(u))),
switchMap(useful => useful.length ? c.get('ghi') : EMPTY)
).subscribe((ghidata) => {
completed...
});
function getUseFulRequests(abcdatas: AbcData[]): Observable<SomeVal>[] {
return abcdatas.reduce((acc, abcdata) => {
if (abcdata.exist) {
const request = b.get('def').pipe(
map(defdatas => defdatas.someval)
)
acc.push(request);
}
return acc;
}, []);
}
Это ничего не выдаст, если getUseFulRequests(abcdatas)
возвращает пустой массив или useful.length == 0
.
Комментарии:
1. Ценю ваш ответ
2. полезно не только для полезных запросов, это массив, сформированный вторым вызовом, т.е. get()
3. @MithunShreevatsa вы можете использовать
tap
для заполнения вашего глобального массива из промежуточного ответа.4. Пожалуйста, пример, как я уже сказал, я новичок, и мне требуется время, чтобы выйти из axios и async, await и promises
5. спасибо, я узнал кое-что очень полезное из вашего ответа и сделал для меня чистый вызов 🙂
Ответ №2:
Я считаю, что лучшим способом справиться с этим будет использование наблюдаемых более высокого порядка
Рассмотрим приведенный ниже код
useful$ = a.get('abc').pipe(
mergeMap(abcdatas =>
abcdata.exist ? forkJoin(abcdatas.map(abcdata => b.get('def'))) : of(undefined)
),
map(defdatas => defdatas.flat()),
mergeMap(({ length }) => length ? c.get('ghi') : of(undefined))
);
useful$.subscribe({
next: () => {
// Completed...
}
})
Сначала мы передаем результат a.get('abc')
и используем mergeMap для проверки, если abcdata.exist
. Если он завершается, мы возвращаем forkJoin(abcdatas.map(abcdata => b.get('def')))
просто, это объединит массив наблюдаемых, сгенерированных из функции map в abcdatas
map(defdatas => defdatas.flat()),
преобразует массив в один массив ПРИМЕЧАНИЕ: flat() был представлен в ES2019
Затем мы разрушаем length
свойство и, если оно существует, возвращаем наш окончательный наблюдаемый
Комментарии:
1. Ценю ваш ответ
Ответ №3:
Я думаю, что то, что вы пытаетесь сделать, это:
a.get("abc").pipe(
mergeMap((abcdatas) => abcdatas.filter((abcdata) => abcdata.exist)), // let's create a stream with all those useful abcdata
mergeMap(abcdata => b.get('def')), // and for each one of those we perform a b.get request
toArray(), // once all the b.get requests have completed, emit a one value stream with an Array of those values values
concatMap(useful => useful.length ? c.get('ghi') : EMPTY) // let's concat that result with the final request
)
Комментарии:
1. Ценю ваш ответ