我正在为@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"
]
由于Angular HttpClientModule
无法加载目录的内容或目录中文件的名称(只能加载单个json文件),因此需要在index.json
中定义名称。 / p>
这也意味着我必须先加载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)。同样,here中所述的解决方案对我也不起作用,因为我需要动态地创建无限数量的可观察对象,并等待它们完成后才能开始步骤 4。(组合全部文件)。
正确的方法应该是什么?
7.1.0
6.3.3
11.0.1
更新
这里的堆叠闪电战:Combining observables
答案 0 :(得分:1)
因此,在搜索并尝试了更多方法后,我找到了答案的解决方案。那里有两个问题:
1。平面图与地图
我使用的是map()
而不是flatMap
。区别在于,当第一个可观察对象完成时,flatMap将执行。这样,直到flatMap observable完成,订阅才能获得结果。
2。 Promise.all与forkJoin
Promise.all()
的可观察等效项是forkJoin()
。 ForkJoin将并行执行所有可观察变量,并在一个数组中返回所有可观察变量的结果。
结果
因此更新上面的代码将导致以下堆叠闪电:solution
或在代码中
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