Here's the demo:
var availableNews$ = Rx.Observable.fromPromise(fetch('https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty').then(res => res.json())); var pager$ = new Rx.Subject(); var fetchedNews$ = Rx.Observable.combineLatest(availableNews$, pager$, (news, pager) => news.slice((pager.current - 1) * pager.items_per_page, pager.items_per_page)) .flatMap(id => id) .map(id => Rx.Observable.fromPromise(fetch(`https://hacker-news.firebaseio.com/v0/item/${id}.json?print=pretty`).then(res => res.json())) .concatMap(res => res)); pager$.subscribe(v => { console.log(v); document.querySelector('#pager').textContent = JSON.stringify(v); }); fetchedNews$.subscribe(x => { console.log(x); document.querySelector('#news').textContent = JSON.stringify(x);; }) pager$.next({current: 1, items_per_page: 10})
<script src="https://unpkg.com/@reactivex/rxjs/dist/global/Rx.js"></script> pager: <p id="pager"></p> news: <p id="news"></p> <p>the news return obserable instance instead of <em>array of fetched news</em> which is desired</p>
I do these things in code:
1, fetch top news feeds (availableNews$)
2, use pager to limit which feeds should be fetch (pager$)
3, fetch news which should be a array (fetchedNews$)
But I stunk at step 3, the results returned is the stream of each promiseObserable, not result of each promise concated as a array.
Thanks for help ^_^
--Edited--
I ask this question as issue for the rxjs on github, and get a better solution. Here's the code:
const { Observable } = Rx;
const { ajax: { getJSON }} = Observable;
var availableNews$ = getJSON('https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty');
var pager$ = new Rx.Subject();
var fetchedNews$ = Observable
.combineLatest(availableNews$, pager$, (news, {current, items_per_page}) => {
return news.slice((current - 1) * items_per_page, items_per_page);
})
.switchMap((ids) => Observable.forkJoin(ids.map((id) => {
return getJSON(`https://hacker-news.firebaseio.com/v0/item/${id}.json?print=pretty`);
})));
pager$.subscribe(v => {
document.querySelector('#pager').textContent = JSON.stringify(v);
});
fetchedNews$.subscribe(stories => {
document.querySelector('#news').textContent = JSON.stringify(stories);
});
pager$.next({current: 1, items_per_page: 10})
You have a combination of two or three errors.
First, the lambda in your combineLatest()
does not operate on the array of news ids, but on a single item containing the array. The flatmap()
is therefore unnecessary, as is the concatMap()
.
Second, you don't need to create Observable
from fetch()
, as
third, the combineLatest()
you have does not give a Promise that is fullfilled when the news are loaded, but when the availableNews and pager are loaded. So you have to make a third Observable
with combineLatest()
, but from the Array of fetch()
Promises. You then subscribe to that in your second subscribe()
, like this:
var availableNews$ = Rx.Observable.fromPromise(fetch('https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty').then(res => res.json())); var pager$ = new Rx.Subject(); var fetchedNews$ = Rx.Observable.combineLatest(availableNews$, pager$, (news, pager) => Rx.Observable.combineLatest.apply(this, news.slice((pager.current - 1) * pager.items_per_page, pager.items_per_page) .map(id => fetch(`https://hacker-news.firebaseio.com/v0/item/${id}.json?print=pretty`).then(res => res.json())))); pager$.subscribe(v => { document.querySelector('#pager').textContent = JSON.stringify(v); }); fetchedNews$.subscribe(x => { x.subscribe(a => { document.querySelector('#news').textContent = JSON.stringify(a); }); }) pager$.next({current: 1, items_per_page: 10})
<script src="https://unpkg.com/@reactivex/rxjs/dist/global/Rx.js"></script> pager: <p id="pager"></p> news: <p id="news"></p> <p>the news return obserable instance instead of <em>array of fetched news</em> which is desired</p>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.