问题
When sending a Get request to Sharepoint URI (e.g. http://company.com.au/teams/Telstra/_api/web/Lists/getbytitle('${listTitle}')/items), it returns a finite number of items (e.g. 30) and provides a link to query to retrieve the next 30 items like so:
I am writing an Angular app to retrieve all items. The pseudo code is like so:
public GetByDomainOwner(listTitle: string, domainNameOwner: string): Observable<any[]> {
let dataToReturn = new Array<any>();
let URI = `http://company.com.au/teams/Telstra/_api/web/Lists/getbytitle('${listTitle}')/items?$filter=DomainOwnerText eq '${domainNameOwner}'`;
var headers: HttpHeaders = new HttpHeaders();
headers.append('Accept', 'application/json;odata=verbose');
while(URI !== undefined){
const records = this.http.get(URI, {
headers: headers,
withCredentials: true
});
records.subscribe(r => {
let data = <SharepointItem> r;
dataToReturn.push(data.d.results);
if(data.d.__next){
URI = data.d.__next;
} else{
URI = undefined;
}
});
}
console.log("Escaped while loop");
return new Observable<any[]>(dataToReturn); // This is invalid obviously, but it describes how I want to make one Observable call to retrieve all data.
}
I want to make the above one single Observable call where it will read and subscribe to d.__next to retrieve the next finite number of items
Using Observable flatmap seems to be quite promising for situations where the depth of nesting is known (e.g. C subscribes to B's stream, of which B subscribes to A's stream). I want to make a flatMap (open to other suggestions) that can repeatedly check and subscribe to more streams without specifying a depth.
回答1:
As @KiraAG commented, expand is probably what you want.
This blog post should have the details you are after: https://blog.angularindepth.com/rxjs-understanding-expand-a5f8b41a3602
The key part is:
import { empty } from "rxjs/observable/empty";
import { concatMap, expand } from "rxjs/operators";
import { get } from "./get";
const url = "https://api.github.com/users/sindresorhus/repos";
const repos = get(url).pipe(
expand(({ next }) => next ? get(next) : empty()),
concatMap(({ content }) => content)
);
repos.subscribe(repo => console.log(repo));
where get(url) returns an observable with the ajax results (content) and the "next" url (to get the next results - held in __next in your example)
来源:https://stackoverflow.com/questions/56520156/nested-observable-with-unknown-nesting-depth