I know, it's a rather complicated question, but I'm very much lost in the RxJs documentation ...
I have an Angular application, and I'm using the OpenLibrary API for creating a homework assignment. I have a service, called SearchService, that uses the /search endpoint. The problem is that this endpoint returns documents that are not in the desirable format, so for each returned document I have to query the actual object from a different endpoint, one-by-one, as batch querying seems to be impossible currently (server just returns HTTP 500).
My solution, that's currently working is as follows:
- Query the
/searchendpoint using Angular'sHttpClient, this function returns anObservable<AuthorSearchResponse> - Pipe this into an RxJs
mapoperator, filter out bad values, and map the result documents (each of them) to anObservable<Author>, that is produced by another service (this.authorService.getAuthorById(id)also usesHttpClientto query and transform a given author by ID) - Pipe this
Observable<Author>[]into amergeMapRxJs operator, that uses theforkJoinoperator. This will produce the desiredAuthor[]array - Pipe this result into a
mapoperator, that transforms this array into the desirableQueryResult<Author>object, that contains an array ofAuthors, as well as the current number of items returned, and it should contain the total number of search results.
This is what my code looks like:
The AuthorSearchResponse interface
interface AuthorSearchResponse {
start: number;
numFound: number;
docs: {
type: string;
key: string;
}[];
}
The QueryResult<T> interface
export interface QueryResult<T> {
totalCount: number;
count: number;
data: T[];
}
My function
// This whole thing produces a QueryResult<Author> instance
return this.httpClient
.get<AuthorSearchResponse>(`${environment.apiUrl}/search/authors.json`, {
params: params,
})
.pipe(
map((searchResponse) =>
searchResponse.docs
.filter(
(doc) => doc.type === 'author' && typeof doc.key !== 'undefined'
)
.map((doc) =>
// getAuthorById returns Observable<Author>
this.authorService.getAuthorById(correctAuthorKey(doc.key))
)
)
)
.pipe(mergeMap((o) => forkJoin(o)))
.pipe(
map((authors) => ({
data: authors,
totalCount: -1,
count: authors.length,
}))
);
My problem is that currently I have no way of passing the searchResponse object to the final operator, which I would very much need to set the totalCount property in the final mapping. Is there any way in RxJs, to take both the searchResponse AND the Observable<Author>[] array produced in the first map operator, and when the forkJoin is finished (all Authors are loaded, and the QueryResult can be produced), use the searchResponse and the produced Author[] in the downstream to combine them into one object?