Эффект NgRX для загрузки медиафайла и отправки хода выполнения. Действия до тех пор, пока не будет отправлено действие «Завершить». - PullRequest
0 голосов
/ 25 августа 2018

Я изучаю NGRX и RXJS в моем проекте Podcast.

Мой текущий вопрос: как вызывать прогресс Действия в моем @effect, основанные на моем действии загрузки.

Эффект выглядит следующим образомэто и работает:

@Effect()
downloadEpisodes$ = this.actions$.ofType( episodeActions.DOWNLOAD_EPISODE )
.pipe(
  map( ( action: episodeActions.DownloadEpisodes ) => action.payload ),
  switchMap( ( episode ) => {
    return this.episodesService
      .download( episode ) // -> download the media file as blobl
      .pipe(
          map( event => this.episodesService.getHttpProgress( event ) ), // => report download progress
          tap( message => {
            console.log( message );

          } ),
          // switchMap( response => new episodeActions.DownloadProgressEpisodes( response ) // => doesn't work cause its not iterable accoring to typescript.
          last(), // => emit last (completed) message to caller
          switchMap( response => {
            return this.episodesService.downloadSuccess( response ) // => process response blob
            .pipe(
              tap( response  => console.log('--->', response )),
              map( response => new episodeActions.DownloadEpisodesSuccess( response ) ),
              catchError( error => of (new episodeActions.DownloadEpisodesFail( error ) ) )
            )
          })
      )
  } )
);

В моей консоли появится следующее сообщение:

Downloading file
episodes.effect.ts:57 File is 7% downloaded.
episodes.effect.ts:57 File is 11% downloaded.
episodes.effect.ts:57 File is 15% downloaded.
episodes.effect.ts:57 File is 18% downloaded.
episodes.effect.ts:57 File is 26% downloaded.
episodes.effect.ts:57 File is 30% downloaded.
episodes.effect.ts:57 File is 44% downloaded.
episodes.effect.ts:57 File is 48% downloaded.
episodes.effect.ts:57 File is 70% downloaded.
episodes.effect.ts:57 File is 74% downloaded.
episodes.effect.ts:57 File is 100% downloaded.
episodes.effect.ts:57 HttpResponse {headers: HttpHeaders, status: 200,             statusText: "OK", url: "http://localhost:3000/episodes/https%3A%2F%2Fwww.s…ple-videos.com%2Faudio%2Fmp3%2Fcrowd-cheering.mp3", ok: true, …}

Что я хочу изменить?

Что ж, tap message в функции getHttpProgress вызывается столько раз, пока загрузка не будет завершена.Затем last() вызов перенаправляет httpResponse на следующий switchMap.

. Чего я хотел бы добиться, так это отправить действие new episodeActions.DownloadProgressEpisodes( message ) во время процесса загрузки (несколько раз) для сохранения загрузкипрогресс в эпизоде ​​(вызовите редуктор, чтобы обновить сущность эпизода).

К сожалению, я не понимаю, как распределять несколько действий DownloadProgressEpisodes во время процесса download без прерывания или последнего switchMapкоторый вызывает this.episodesService.downloadSuccess( response ).Я пытался добавить вызов действия после tap, до вызова last, так как это казалось Iterator.Тем не менее, он не отправлял эти действия, ничего не обнаружилось в моем приставке devTool.Когда я отправляю DownloadProgressEpisode из моего сервиса в рамках вызова getHttpProgress, он работает, но я не уверен, что это правильный путь.

В конце я хочу увидеть следующее в моем приставке devTool:

[Podcast] Download Episode;
[Podcast] Download Episode Progress; // payload 0%
[Podcast] Download Episode Progress; // payload 10%
...etc
[Podcast] Download Episode Progress; // payload 100%
[Podcast] Download Episode Success;

Каков наилучший способ решить эту проблему?

Или, альтернативно, я должен использовать различные эффекты для загрузки, которая вызывает эффект для DownloadProgress, который повторяется до завершения итогда вызов и эффект для DownloadSuccess?

1 Ответ

0 голосов
/ 25 августа 2018

Я бы разделил этот эффект на несколько меньших. Прямо сейчас вы делаете несколько вещей с одинаковым эффектом: загрузка, обновление прогресса и обработка результата. Вы можете попытаться создать эффект для каждого из них.

Скачать эпизод:

@Effect()
downloadEpisode$ = this.actions$.pipe(
  ofType(episodeActions.DOWNLOAD_EPISODE),
  switchMap(({ payload }) => this.episodesService
      .download(payload).pipe(
         map(response => new episodeActions.DownloadEpisodesSuccess(response)),
         catchError(err => of(new episodeActions.DownloadEpisodesFail(error))),
      )
  )
)

Поймайте действие успешной загрузки и обработайте его:

@Effect()
processEpisode$ = this.actions$.pipe(
  ofType(episodeActions.DOWNLOAD_EPISODE_SUCESS),
  switchMap(({ payload }) => this.episodesService
      .downloadSuccess(payload).pipe(
         map(response => new episodeActions.ProcessEpisodesSuccess(response)),
         catchError(err => of(new episodeActions.ProcessEpisodesFail(error))),
      )
  )
)

А о показе / обновлении прогресса:

@Effect()
updateProgress$ = this.actions$.pipe(
  ofType(episodeActions.DOWNLOAD_EPISODE),
  switchMap(({ payload }) => this.episodesService
      .getHttpProgress(payload).pipe(
         map(res => new episodeActions.DownloadEpisodesProgress(res)),
      )
  )
)

Этот способ отображения прогресса предполагает, что метод getHttpProgress будет возвращать новую наблюдаемую информацию при каждой загрузке нового эпизода. Мы перечислили действие, которое уведомляет о том, что загрузка началась, и затем переключаем карту на вывод getHttpProgress.

...