I am learning NGRX and RXJS in my Podcast project.
My current question is: how to call progress Actions within my @effect based on my Download Action.
The effect looks like this and works:
@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 ) ) )
)
})
)
} )
);
This will report the following in my console:
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, …}
What do I want to change?
Well, the tap message
under the getHttpProgress
function is called as many times until the upload is done. Then the last()
call forwards the httpResponse
to the next switchMap
.
What I would like to achieve is to dispatch an action new episodeActions.DownloadProgressEpisodes( message )
during the Download progress (multiple times) to store the download progress within the episode (call the reducer to update the episode entity).
Unfortunately, I don't understand how to dispatch multiple DownloadProgressEpisodes
actions during the download
process without breaking or the last switchMap
that calls the this.episodesService.downloadSuccess( response )
.
I tried to add a action call after the tap
, before the last
call as it seemed to be an Iterator
. However, it didn't dispatch those actions, nothing showed up in my redux devTool.
When I dispatch the DownloadProgressEpisode
from my service within the getHttpProgress
call, It works but I am not sure if that is the proper way.
In the end I want to see the following in my 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;
What is the best way to solve this?
Or alternatively, should I use different effects for the Download, which calls an effect for the DownloadProgress which repeats itself until finished and then call and effect for DownloadSuccess?