简体   繁体   中英

Rx.js: get all results as array from promise lists

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM