Я хотел бы делать рекурсивные HTTP-вызовы API с разбивкой по страницам, пока не пройдусь по всем страницам. Каждая страница содержит массив ресурсов, которые я объединю во временный массив. Прочитав все страницы, я хочу вернуть один массив всех активов в качестве наблюдаемого.
Я использовал трубу с оператором расширения. Я заметил, что смогу распечатать свой окончательный массив после завершения подписки, но я не знаю, как элегантно вернуть этот массив как наблюдаемый. Есть ли способ дождаться завершения одной наблюдаемой и затем вернуть другую?
getAllAssets(sort: string, filter: AssetFilter): Observable<Asset[]> {
let allAssets: Asset[] = [];
console.log('getAllAssets()', sort, filter);
this._getAllAssets(null, null).subscribe((moreAssets) => {
allAssets = allAssets.concat(moreAssets);
}, null, () => console.log(allAssets));
return of(allAssets);
}
_getAllAssets(sort: string, filter: AssetFilter) {
let currentPage = 0;
return this.getAssets(null, null, sort, filter).pipe(
expand(assetsPage => {
if (assetsPage && assetsPage.page.number + 1 < assetsPage.page.totalPages) {
return this.getAssets(currentPage += 1, null, sort, filter);
}
return empty();
}),
map((value) => value._embedded.assets)
);
}
getAssets(page: number, size: number, sort: string, filter: AssetFilter): Observable<Assets> {
let url = 'https://gateway.' + environment.region + '.mindsphere.io/api/assetmanagement/v3/assets?';
if (page) {
url += 'page=' + page;
}
if (size) {
url += 'size=' + size;
}
if (sort) {
url += 'sort=' + sort;
}
if (filter) {
url += 'filter=' + JSON.stringify(filter);
}
return this.http.get<Assets>(url, {
headers: new HttpHeaders().set('Content-Type', 'application/json').set('Authorization', 'Bearer ' + this.accessToken)
});
}
Я получаю правильный массив, напечатанный на экране, но я бы хотел вернуть этот массив как наблюдаемый, не создавая наблюдаемую, вернуть наблюдаемую и выдать ее при завершении.
EDIT:
Мое исправление должно было использовать toArray()
как упомянуто ниже. Затем я просто сделал карту, чтобы превратить Observable<item[][]>
в Observable<item[]>
getAllAssets(sort: string, filter: AssetFilter): Observable<Asset[]> {
let currentPage = 0;
return this.getAssets(null, null, sort, filter).pipe(
expand(assetsPage => {
if (assetsPage && assetsPage.page.number + 1 < assetsPage.page.totalPages) {
return this.getAssets((currentPage += 1), null, sort, filter);
}
return empty();
}),
map(value => value._embedded.assets),
toArray()
).pipe(map(assets => [].concat.apply([], assets)));
}
getAssets(page: number, size: number, sort: string, filter: AssetFilter): Observable<Assets> {
let url = 'https://gateway.' + environment.region + '.mindsphere.io/api/assetmanagement/v3/assets?';
if (page) {
url += 'page=' + page;
}
if (size) {
url += 'size=' + size;
}
if (sort) {
url += 'sort=' + sort;
}
if (filter) {
url += 'filter=' + JSON.stringify(filter);
}
return this.http.get<Assets>(url, {
headers: new HttpHeaders().set('Content-Type', 'application/json').set('Authorization', 'Bearer ' + this.accessToken)
});
}