angular - Rxjs 结合动态数量的 observables
问题描述
我正在为@ngx-translate创建一个加载器,它根据所选语言从一个目录加载多个 JSON 翻译文件。
我目前加载文件的方式是通过一个index.json
文件,该文件包含一个数组,其中包含该语言翻译文件的名称和扩展名。
翻译文件的结构如下:
- assets
- i18n
- index.json <-- Contains an array of translation file names
- en_US
- home.json
- header.json
- de_DE
- home.json
- header.json
一个例子index.json
如下:
[
"home.json",
"header.json"
]
由于 AngularHttpClientModule
无法加载目录的内容或目录中的文件名(它只能加载单个 json 文件),我需要在index.json
.
这也意味着我必须先加载 index.json,然后再加载目录中的所有其他文件。
在代码中,这意味着以下内容:
- 加载 index.json
- 循环遍历文件名数组
- 在单独的请求中加载每个文件
- 全部完成后将所有文件内容合并到一个对象中
我试过的
public getTranslation(language: string): Observable<any> {
return this.getIndexFile(language)
.pipe(
map((fileNames: string[]) => {
const promises = [];
for (const name of fileNames) {
const path = Translation.replaceUrlPlaceholder(this.path, language);
promises.push(this.http.get(path + '/' + name + '.json').toPromise());
}
return Promise.all(promises);
}),
);
}
所以我已经用 promises 尝试了这个,但这显然不起作用(因为必须返回一个 observable)。此外,此处描述的解决方案对我也不起作用,因为我需要动态创建无限数量的可观察对象并等待它们完成,然后才能开始第 4 步。(合并所有文件)。
正确的方法应该是什么?
- 角
7.1.0
- RxJS
6.3.3
- @ngx-翻译/核心
11.0.1
更新
Stackblitz 在这里:组合可观察对象
解决方案
因此,在搜索并尝试更多之后,我找到了答案的解决方案。那里有2个问题:
1.平面图与地图
我使用的是 amap()
而不是 a flatMap
。不同之处在于 flatMap 将在第一个 observable 完成时执行。这样,在 flatMap 可观察对象完成之前,订阅不会得到结果。
2. Promise.all 与 forkJoin
的可观察等价物Promise.all()
是forkJoin()
。ForkJoin 将并行执行所有 observable,并在一个数组中返回所有 observable 的结果。
结果
所以更新上面的代码会导致下面的stackblitz :
或在代码中:
public getTranslation(language: string): Observable<any> {
return this.getIndexFile(language)
.pipe(
flatMap((fileNames: string[]) => {
const observables: Observable<any>[] = [];
for (const name of fileNames) {
const path = 'assets/i18n/' + language + '/' + name + '.json';
observables.push(this.http.get(path));
}
// Run all the observables in parallel
return forkJoin(observables);
}),
);
关注点分离
我的代码在一个函数中包含多个操作,这使得测试变得困难。所以应该分开。@trichetriche 制作了一个包含关注点分离的版本。
有关代码,请参见他的 Stackblitz:Stackblitz
推荐阅读
- vim - 错误 CocAction("extensionStats") 不起作用
- java - ItemCount 未更新
- javascript - 如何在编辑器内容更改时将ckeditor5内容发送到python烧瓶
- delphi - Delphi 中的注释会减慢执行时间吗?
- reactjs - useEffect 不验证布尔值以执行某些操作
- bigcommerce - 如何在 Bigcommerce 中更改 H1 标题(产品页面上的产品描述)的大小
- json - Json Schema if/then 没有按预期工作
- java - 无法使用 jdbc 驱动程序连接到 mysql
- oracle - PL/SQL 动态 SQL 在函数中带单引号
- python - 根据 NaN 值使用 .apply() 更改 DataFrame