When requesting urlFirst we get data. If the data contains a key with a value of 'nextPage', you need to make a request for urlNextPage to get additional data, and so on, until the nextPage key is in the response with the urlNextPage. urlNextPage in each answer comes different.

The object has the following structure:

{ "id": 6, "price": 784, "links": [{ "status": "selfPage", "url": "urlSelf" }, { "status": "nextPage", "url": "urlNextPage" } ] } 

It is necessary to collect data from urlFirst and from all recursive calls urlNextPage in one array.

I tried to do the usual recursion, but I can’t get everything right.

 let arr = []; getData() { this.httpGeneralService.getDataServer(`urlFirst `) .subscribe(e => { this.arr.push(e.price); this.recursive(e); }); } recursive(e) { for (const obj in e.links) { if (e.links[obj].status === 'nextPage') { this.httpGeneralService.getDataFromJsonServer(e.links[obj].url) .pipe(map(item => { this.arr.push(item.price); return item; })) .subscribe(z => { this.recursive(z); }); } } } 

    1 answer 1

    Do not use for loops and if conditions in conjunction with RxJS. For this there is a from function, which takes 3 types of arguments as a parameter - a stream, a Promise and an array + a filter operator.

    What's going on here? We make a request for urlFirst , get an object with the links property (if I understood correctly from your code).

    Using from in a loop, we go through the links array and filter the link whose status is nextPage . After that, call getDataFromJsonServer , which also returns an object in the stream with price and links properties. Push price into the array and again call the recursive function with these links.

     getData() { this.httpGeneralService.getDataServer(`urlFirst `).pipe( tap(({ price }) => this.array.push(price)), switchMap(({ links }) => this.recursive(links)) ).subscribe(() => { console.log(this.array); }); } recursive(links) { return from(links).pipe( filter(({ status }) => status === 'nextPage'), mergeMap(({ url }) => this.httpGeneralService.getDataFromJsonServer(url).pipe( map(({ price, links }) => { this.array.push(price); return links; }), mergeMap((links) => this.recursive(links)) )) ); } 
    • Supper! Thank! Yes, an object comes with the links property, which has a slightly different structure (I added in the question). I don’t understand how to filter such a structure using from / filter - Lex
    • I was already looking in the direction of expand for recursion - Lex
    • Well, look, you have the links array - you need to pass it to the from function, from will loop through it (what you do with for ), inside the filter we already get elements from the array (object { status: '...', url: '...' } ), we pass the predicate to the filter, that we must perform further actions only for array elements whose status === 'nextPage' , will not help you - overthesanity
    • if status === 'nextPage' - then we take the url from the object and make a new request, we get an answer, push the price into the array and call this.recursive for the new array of links - overthesanity again
    • In my simple MergeMap, the url linter selects as: The property "url" does not exist in the type "{status: any;}". - Lex