【发布时间】:2019-12-09 22:00:58
【问题描述】:
我知道在 subscribe 中调用 subscribe 是不好的做法,但我不知道如何在我的特殊情况下以不同的方式处理它。 现在的代码可以工作,但我的问题是,如果我每秒更新我的网站,则首先加载表格的一部分,然后加载其他部分(我订阅中的订阅内容)。
我有一个服务,其中包含一个函数,该函数返回不同资产的文件列表的 Observable。 在该函数中,我通过调用另一个服务来请求每个资产的文件列表,并且该服务返回 observables。 然后我遍历该列表的元素并构建我的数据结构以便稍后返回它们(AssetFilesTableItems)。 有些文件可以是 zip 文件,我想通过订阅另一个服务(extractZipService)来获取这些文件的内容。为了能够获得正确的数据,我需要通过请求文件列表获得的文件的名称。然后我将 zip 内容的一些数据添加到我的 AssetFilesTableItems 并在最后返回所有内容。
该函数的代码如下:
getAssetfilesData(assetIds: Array<string>, filter: RegExp, showConfig: boolean): Observable<AssetFilesTableItem[][]> {
const data = assetIds.map(assetId => {
// for each assetId
return this.fileService.getFileList(assetId)
.pipe(
map((datasets: any) => {
const result: AssetFilesTableItem[] = [];
// iterate over each element
datasets.forEach((element: AssetFilesTableItem) => {
// apply regex filter to filename
if (filter.test(element.name)) {
this.logger.debug(`Filter ${filter} matches for element: ${element.name}`);
// build up AssetFilesTableItem
const assetFilesItem: AssetFilesTableItem = {
name: element.name,
type: element.type,
asset: assetId
};
// save all keys of AssetFilesTableItem
const assetFilesItemKeys = Object.keys(assetFilesItem);
// if file is of type ZIP, extract 'config.json' from it if available
if (showConfig && element.type.includes('zip')) {
this.extractZipService.getJSONfromZip(assetId, element.name, 'config.json')
.subscribe((configJson: any) => {
const jsonContent = JSON.parse(configJson);
const entries = Object.entries(jsonContent);
entries.forEach((entry: any) => {
const key = entry[0];
const value = entry[1];
// only add new keys to AssetFilesTableItem
if (!assetFilesItemKeys.includes(key)) {
assetFilesItem[key] = value;
} else {
this.logger.error(`Key '${key}' of config.json is already in use and will not be displayed.`);
}
});
});
}
result.push(assetFilesItem);
}
});
return result;
}));
});
// return combined result of each assetId request
return forkJoin(data);
}
}
我在组件中使用以下代码更新表:
getValuesPeriodically(updateInterval: number) {
this.pollingSubscription = interval(updateInterval)
.subscribe(() => {
this.getAssetfilesFromService();
}
);
}
getAssetfilesFromService() {
this.assetfilesService.getAssetfilesData(this.assetIds, this.filterRegEx, this.showConfig)
.subscribe((assetFilesTables: any) => {
this.assetFilesData = [].concat.apply([], assetFilesTables);
});
}
编辑:我尝试了 ForkJoin,但据我了解,它用于并行执行更多请求。我的 extractZipService 虽然取决于我从 fileService 获得的结果。我最后也有一个 forkJoin,它应该结合我对不同资产的所有 fileList 请求。我不明白为什么我的视图没有立即加载。
编辑:问题似乎是在我的 fileService 订阅的 forEach 中订阅了 extractZipService。它似乎在 fileService 订阅之后完成。我已经尝试了很多东西,比如 SwitchMap、mergeMap 和这里建议的解决方案,但没有运气。我确信有可能让它以某种方式工作,但我的想法已经不多了。任何帮助,将不胜感激!
【问题讨论】:
-
在接受的答案中查看
forkJoin以并行运行请求 -
据我了解,forkJoin 用于并行执行更多请求,但我的 extractZipService 取决于我从 fileService 获得的结果。我最后也有一个 forkJoin,它可以结合我对不同资产的所有 fileList 请求。我不明白为什么我的视图没有立即加载。
-
好的,当时有点仓促,没有正确阅读。对不起,我的错。我重新打开了问题:)
标签: javascript angular typescript rxjs