Rxjs Объединить динамическое количество наблюдаемых - PullRequest
0 голосов
/ 27 ноября 2018

Я создаю загрузчик для @ 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);
        }),
      );
  }

Итак, я попробовал это с обещаниями, но это, очевидно, не работает (так как наблюдаемое должно быть возвращено).Кроме того, решение, описанное здесь , не работает для меня, так как мне нужно динамически создать неограниченное количество наблюдаемых и ждать их завершения, прежде чем я смогу начать на шаге 4. (объединить все файлы).

Каким должен быть правильный способ сделать это?


  • Угловой 7.1.0
  • RxJS 6.3.3
  • @ ngx-translate / core 11.0.1

Обновление

Stackblitz здесь: Объединение наблюдаемых

1 Ответ

0 голосов
/ 27 ноября 2018

Так что после поиска и попытки еще раз я нашел решение моего ответа.Там где 2 проблемы:

1.Плоская карта против карты

Я использовал map() вместо flatMap.Разница в том, что flatMap будет выполняться, когда закончится первая наблюдаемая.Таким образом, подписка не получит результат, пока не закончится наблюдаемая квартира.

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

...