在浏览完所有页面之前,我想对分页的API进行递归HTTP调用。每个页面包含一个资产数组,我将这些资产连接到一个临时数组。阅读完所有页面后,我想返回所有资产的单个数组作为可观察值。
我一直在使用管道与expand运算符。我注意到我可以在订阅完成时打印我的最终数组,但是我不知道如何优雅地返回此数组作为可观察的数组。有什么方法等待一个可观察的对象完成然后返回另一个?
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)
});
}
我正在将正确的数组打印到屏幕上,但是我想将此数组作为可观察对象返回,而无需创建可观察对象,返回可观察对象,并在完成时将其发送给它。
编辑:
我的解决方法是使用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)
});
}
答案 0 :(得分:0)
答案 1 :(得分:0)
需要花一些代码进行筛选,因此我将对其进行归纳和归纳,因为这是一种常见的模式,它将采用以下形式:
_getAllPages(page, constantArgs, lastSet) {
lastSet = lastSet || []; // deal with entry
return this.getPage(page, constantArgs).pipe( // fetch the page
switchMap(res =>
(res.nextPage) // if nextpage, recurse and concat to last set
? this._getAllPages(res.nextPage, lastSet.concat(res.items))
: of(lastSet.concat(res.items)))); // else break
}
出于样式目的,我通常将其设为私有,而将使用public:
getAllPages(constantArgs) {
return this._getAllPages(0, constantArgs);
}
使API更好/更易于理解。