angular - 用于下载媒体文件和调度进度的 NgRX 效果,直到调度完成操作

标签 angular ngrx ngrx-effects

我正在我的 Podcast 项目中学习 NGRX 和 RXJS。

我当前的问题是:如何根据我的下载操作在我的@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, …}

我想改变什么?

好吧,getHttpProgress 函数下的tap message 会被多次调用,直到上传完成。然后 last() 调用将 httpResponse 转发到下一个 switchMap

我想要实现的是在下载进度(多次)期间分派(dispatch)一个操作 new episodeActions.DownloadProgressEpisodes( message ) 以存储剧集中的下载进度(调用 reducer 更新剧集实体)。

不幸的是,我不明白如何在 download 过程中分派(dispatch)多个 DownloadProgressEpisodes 操作而不中断或调用最后一个 switchMap this.episodesService.downloadSuccess(响应)。 我尝试在 tap 之后、last 调用之前添加一个 Action 调用,因为它看起来像是一个 Iterator。但是,它没有发送这些操作,我的 redux devTool 中没有显示任何内容。 当我在 getHttpProgress 调用中从我的服务发送 DownloadProgressEpisode 时,它有效但我不确定这是否是正确的方法。

最后我想在我的 redux 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 并产生效果?

最佳答案

我会将这种效果分成几个较小的效果。现在您正在做几件相同的事情:下载、更新进度和处理结果。您可以尝试为它们中的每一个创建一个效果。

下载剧集:

@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))),
      )
  )
)

捕获下载成功 Action 并处理它:

@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 的输出。

关于angular - 用于下载媒体文件和调度进度的 NgRX 效果,直到调度完成操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52013359/

相关文章:

javascript - Angular 2 中的一个组件如何通过调用另一个组件的方法来弹出另一个组件?

javascript - ionic 显示阵列导致模板

angular - mergeMap 中与 @ngrx 的并行操作?

angular - 发送 :false 时测试@Effect

javascript - Angular/ngrx 应用程序在注销单击时中断

带参数的 Angular2 辅助路由

angular - 错误 NullInjectorError : R3InjectorError(DynamicTestModule)[KDSDialogService -> MatDialog -> MatDialog]: NullInjectorError: No provider for MatDialog

ngrx - @ngrx/Store 如何用于缓存?

node.js - 如何等待发货完成后再从商店挑选。 Ngrx相关问题

angular - 为什么在此 ngrx 示例中需要 takeUntil?