I am fetching data from API that return a array of objects. Each object contains a link to which I have to make a GET request again to get the final result. This is how I have implemented this.
return this.client.request(new HttpRequest("GET", request, {
headers: new HttpHeaders({
Authorization: `bearer ${environment.vimeoConfig.accesstoken}`
})
})).pipe(
filter((response) => {
return response instanceof HttpResponse
}),
tap((res: HttpResponse < any > ) => {
pagingQuery.maxpages = (res.body.total / batchSize);
if (pagingQuery.maxpages % 1 > 0) pagingQuery.maxpages = Math.floor(pagingQuery.maxpages) + 1
pagingQuery.page++;
}),
map((res: HttpResponse < any > ) => (res.body.data as any[]).map((data) => {
return {
id: data.uri.split('/')[2],
title: data.name,
desc: data.description,
date: data.created_time,
thumbid: "",
durationInSeconds: data.duration,
links: new Map(data.files.map(file => [file.height ? ? 'hls', file.link])),
videoObservable: this.client.get(`https://api.vimeo.com${data.pictures.uri}?sizes=96x54`, {
headers: new HttpHeaders({
Authorization: `bearer ${environment.vimeoConfig.accesstoken}`
})
})
}
as VimeoVid;
}))
)
So I am returning the observable for each object.
In the HTML I am doing the following
<mat-list-option class="option" *ngFor="let vid of vids" [value]="vid">
<mat-radio-button color="primary" [checked]="_selectedVid === vid"></mat-radio-button>
<ng-container *ngIf="vid.videoObservable | async as thumb else optionSkeleton">
<img [src]="thumb.sizes[0].link">
</ng-container>
<div class="vid-title sub1">{{vid.title}}</div>
<div class="sub1">Private link</div>
<div class="sub1">{{format(vid.date)}}</div>
</mat-list-option>
I know this is not the way to do this. What is a better way to implement this?
I have not tested it but it could be this way.
I have used property video instead of videoObservable, also make sure you don't use async pipe in template.
First, let's divide our code into doPageCalc, getVideos
return this.client.request(new HttpRequest("GET", request, {
headers: new HttpHeaders({
Authorization: `bearer ${environment.vimeoConfig.accesstoken}`
})
})).pipe(
filter(response => response instanceof HttpResponse),
tap((res: HttpResponse < any > ) => this.doPageCalc(res)),
map((res: HttpResponse < any > ) => this.getVideos(res))
);
doPageCalc(res: HttpResponse < any >): any{
pagingQuery.maxpages = (res.body.total / batchSize);
if (pagingQuery.maxpages % 1 > 0) pagingQuery.maxpages = Math.floor(pagingQuery.maxpages) + 1
pagingQuery.page++;
}
getVideos(res: HttpResponse < any >): Observable<VimeoVid[]>{
const bodyData = res.body.data as any[];
// create stream from of each data
return from(bodyData).pipe(
// run in parallel for each bodyData
mergeMap(data => of(data).pipe(
// switch to get video
switchMap(d => this.getVideo(d)),
// combine video metaData with actual video data
map(video => ({ ...this.getVideoMeta(data), video } as VimeoVid))
)
),
toArray()
);
}
getVideo(data: any): Observable<any>{
this.client.get(`https://api.vimeo.com${data.pictures.uri}?sizes=96x54`, {
headers: new HttpHeaders({
Authorization: `bearer ${environment.vimeoConfig.accesstoken}`
})
});
}
getVideoMeta(data: any): any{
return {
id: data.uri.split('/')[2],
title: data.name,
desc: data.description,
date: data.created_time,
thumbid: "",
durationInSeconds: data.duration,
links: new Map(data.files.map(file => [file.height ? ? 'hls', file.link]))
};
}