RxJs Наблюдаемых Пагинации
First: это первый проект, в котором я использую RxJs, я думал, что лучше всего узнаю, используя его.
Я нашел такой ответ: превращение разбитых на страницы запросов в наблюдаемый поток с помощью RxJs Но в комментариях сказано:
вы все еще превышаете максимальный стек вызовов. Около 430 страниц вернулся. Я думаю, что рекурсия может быть не лучшим решением здесь
Я хочу запросить API данных Youtube, результаты вернитесь на страницы, и мне нужно пролистать их. Я представлял, что такой рабочий поток может сработать.: 1)инициировать вызов 2) Проверьте, имеет ли ответ "nextPageToken" 3) Если это так, сделайте еще один запрос в API Youtube 4)Если нет, отделка
So to do this I could Imagine the following Observables / streams:
FirstRequestStream -A-X--------------->
ResponseStream -A-A-A-A--X-------->
RequestStream -I-A-I-A----------->
A = Action
I = Info from upper stream
X = Termination
(Не уверен, что эта диаграмма верна так, как я ее сделал)
таким образом, ResponseStream зависит от FirstRequestStream и RequestStream(используя функцию слияния). RequestStream зависит от ResponseStream( это называется циркулирующий наблюдаемый ?)
-это правильный подход ?
- любой другой способ, который я должен попробовать сначала?
- возможно ли создать взаимозависимые наблюдаемые потоки ?
Спасибо за помощь.
1 ответов
вы усложняете эту проблему,ее можно решить намного проще с помощью оператора defer.
идея заключается в том, что вы создаете отложенный наблюдаемый (поэтому он будет создан и начнет получать данные только после подписки) и объедините его с тем же наблюдаемым, но для следующей страницы, которая также будет объединена со следующей страницей, и так далее ... . И все это можно сделать без рекурсии.
вот как код выглядит так:
const { defer, from, concat, EMPTY, timer } = rxjs; // = require("rxjs")
const { mergeMap, take, mapTo, tap } = rxjs.operators; // = require("rxjs/operators")
// simulate network request
function fetchPage(page=0) {
return timer(100).pipe(
tap(() => console.log(`-> fetched page ${page}`)),
mapTo({
items: Array.from({ length: 10 }).map((_, i) => page * 10 + i),
nextPage: page + 1,
})
);
}
const getItems = page => defer(() => fetchPage(page)).pipe(
mergeMap(({ items, nextPage }) => {
const items$ = from(items);
const next$ = nextPage ? getItems(nextPage) : EMPTY;
return concat(items$, next$);
})
);
// process only first 30 items, without fetching all of the data
getItems()
.pipe(take(30))
.subscribe(e => console.log(e));
<script src="https://unpkg.com/rxjs@6.2.2/bundles/rxjs.umd.min.js"></script>