[英]Rxjs Combine dynamic amount of 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"
]
由於Angular HttpClientModule
無法加載目錄的內容或目錄中文件的名稱(它只能加載單個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);
}),
);
}
所以我已經嘗試過用Promise進行嘗試,但這顯然行不通(因為必須返回一個Observable)。 同樣, 這里描述的解決方案對我不起作用,因為我需要動態地創建無限數量的可觀察對象,並等待它們完成之后才能開始第4步。(合並所有文件)。
正確的方法應該是什么?
7.1.0
6.3.3
11.0.1
更新
Stackblitz在這里: 結合可觀察物
因此,在搜索並嘗試了更多方法之后,我找到了答案的解決方案。 那里有兩個問題:
1.平面圖與地圖
我使用的是map()
而不是flatMap
。 區別在於,當第一個可觀察對象完成時,flatMap將執行。 這樣,直到flatMap observable完成,訂閱才能獲得結果。
2. Promise.all與fork
Promise.all()
的可觀察等效項是forkJoin()
。 ForkJoin將並行執行所有可觀察變量,並在一個數組中返回所有可觀察變量的結果。
結果
因此,更新上面的代碼將導致以下堆棧閃電: 解決方案
或在代碼中:
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.