【问题标题】:Rxjs Combine dynamic amount of observablesRxjs 结合动态数量的 observables
【发布时间】:2018-11-27 09:27:40
【问题描述】:

我正在为@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,然后再加载目录中的所有其他文件。

在代码中,这意味着:

  1. 加载 index.json
  2. 遍历文件名数组
  3. 在单独的请求中加载每个文件
  4. 全部完成后将所有文件内容合并到一个对象中

我的尝试

 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
  • RxJS 6.3.3
  • @ngx-translate/核心11.0.1

更新

这里是 Stackblitz:Combining observables

【问题讨论】:

  • 请提供minimal reproducible example 重现该问题。
  • @tricheriche,更新了更多详细信息。您是否遗漏了任何内容,或者这是否符合 stackoverflow 帖子的规则? :)
  • stackblitz.com 上的沙盒是最好的,因为它可以让我们简单地实施我们为您提供的解决方案。
  • @trichetriche,添加了一个 stackblitz 来重现我的问题。
  • 抱歉,我在旁边工作。我有made a stackblitz,功能和用法明确分离,请随时查看!

标签: angular typescript rxjs observable


【解决方案1】:

所以在搜索并尝试了更多之后,我找到了答案的解决方案。有2个问题:

1.平面图与地图

我使用的是map() 而不是flatMap。不同之处在于 flatMap 将在第一个 observable 完成时执行。这样,在 flatMap 可观察对象完成之前,订阅不会得到结果。

2。 Promise.all 与 forkJoin

Promise.all() 的可观察等效项是 forkJoin()。 ForkJoin 将并行执行所有 observable,并在一个数组中返回所有 observable 的结果。


结果

所以更新上面的代码会导致下面的stackblitz: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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-15
    相关资源
    最近更新 更多