Angular6 下载媒体文件和调度进度的NgRX效果;如何处理流和节流
我在理解和应用@Effects作为我的剧集下载选项方面有点困难。我在另一个问题上得到了一些帮助,这是我的最新配方 快速概述:用户单击下载,发送第一个效果中捕获的Angular6 下载媒体文件和调度进度的NgRX效果;如何处理流和节流,angular6,ngrx,ngrx-effects,Angular6,Ngrx,Ngrx Effects,我在理解和应用@Effects作为我的剧集下载选项方面有点困难。我在另一个问题上得到了一些帮助,这是我的最新配方 快速概述:用户单击下载,发送第一个效果中捕获的download\u插曲操作。下载调用返回HttpEvents流和最终HttpResponse 在event.type==3期间,我想报告下载进度。当event.type===4主体到达时,我可以调用success,例如它可以创建一个Blob 服务插曲服务: download( episode: Episode ): Observable
download\u插曲
操作。下载调用返回HttpEvents流和最终HttpResponse
在event.type==3
期间,我想报告下载进度。当event.type===4
主体到达时,我可以调用success,例如它可以创建一个Blob
服务<代码>插曲服务:
download( episode: Episode ): Observable<HttpEvent<any>> | Observable<HttpResponse<any>> {
// const url = encodeURIComponent( episode.url.url );
const url = 'https%3A%2F%2Fwww.sample-videos.com%2Faudio%2Fmp3%2Fcrowd-cheering.mp3';
const req = new HttpRequest( 'GET', 'http://localhost:3000/episodes/' + url, {
reportProgress: true,
responseType: 'blob'
} );
return this.http.request( req );
}
downloadSuccess( response: any ): Observable<any> {
console.log( 'calling download success', response );
if ( response.body ) {
var blob = new Blob( [ response.body ], { type: response.body.type } );
console.log( 'blob', blob );
}
return of( { status: 'done' } );
}
getHttpProgress( event: HttpEvent<any> | HttpResponse<Blob> ): Observable<DownloadProgress> {
switch ( event.type ) {
case HttpEventType.DownloadProgress:
const progress = Math.round( 100 * event.loaded / event.total );
return of( { ...event, progress } );
case HttpEventType.Response:
const { body, type } = event;
return of( { body, type, progress: 100 } );
default:
return of( { ...event, progress: 0 } );
}
}
你认为这是最好的解决方案吗?类型3和类型4是分开的,我可以控制它
*更新2:
它确实会产生一个问题,即在下载成功
进度为100%的操作后,可以触发进度为97%的进度操作。
每次我遇到新的挑战
SampleTime(500)
似乎有效,因为它似乎不会在出现类型4事件之后抛出类型3事件
*更新3:我刚刚发现我现在打了两次电话Download
,效果是,叹气。我回到原点,试图阻止来自EpicodeService.download的HttpEvent流。我认为如果您不想使用if-else
语句,您必须创建不同的效果
在当前操作中,您将使用有效负载中的类型分派一个新操作,例如downloadEpisodeProges
。
然后,您将创建两个监听此操作的效果,并通过类型对其进行相应过滤,一个效果将用于分派DownloadProgressSpices
,另一个用于DownloadSpicesSuccess
另一个可能的解决方案是,但我没有将其与NgRx效果结合使用
记住,对于您进行的每个订阅,都会有性能成本,我个人并不介意if-else
语句。我也查看了分区操作符。不确定它是否适用于NGRX,我尝试了,但失败了。但我可以再试一次。我也不介意IF-ELSE,我只想限制为事件类型3调度的操作量。
@Effect()
downloadEpisode$ = this.actions$.pipe(
ofType<episodeActions.DownloadEpisodes>( episodeActions.DOWNLOAD_EPISODE ),
switchMap( ( { payload } ) => this.episodesService.download( payload )
.pipe(
switchMap( (response: HttpEvent<any> | HttpResponse<any>) => this.episodesService.getHttpProgress( response ) ), //merge in the progress
map( ( response: fromServices.DownloadProgress ) => {
// update the progress in the episode
//
if ( response.type <= 3 ) {
return new episodeActions.DownloadProgressEpisodes( { ...payload, download: {
progress: response.progress
} } );
// pass the Blob on the download response
//
} else if ( response.type === 4 ){
return new episodeActions.DownloadEpisodesSuccess( response );
}
} ),
catchError( error => of( new episodeActions.DownloadEpisodesFail( error ) ) ),
)
)
)
@Effect( { dispatch: false } )
processDownloadEpisodeSuccess$ = this.actions$.pipe(
ofType<any>( episodeActions.DOWNLOAD_EPISODE_SUCCESS ),
switchMap( ( { payload } ) => this.episodesService
.downloadSuccess( payload ).pipe(
tap( response => console.log( 'response', payload,response ) ),
// catchError(err => of(new episodeActions.ProcessEpisodesFail(error))),
)
)
)
@Effect( )
downloadEpisode$ = this.actions$.pipe(
ofType<episodeActions.DownloadEpisodes>( episodeActions.DOWNLOAD_EPISODE ),
switchMap( ( { payload } ) => this.episodesService.download( payload )
.pipe(
switchMap( (response: HttpEvent<any> | HttpResponse<any>) => this.episodesService.getHttpProgress( response ) ),
throttleTime( 500 ),
map( ( response: fromServices.DownloadProgress ) => {
console.log('Type 3', response);
// update the progress in the episode
if ( response.type <= 3) {
return new episodeActions.DownloadProgressEpisodes( { ...payload, download: {
progress: response.progress
} } );
}
} ),
catchError( error => of( new episodeActions.DownloadEpisodesFail( error ) ) ),
)
)
)
@Effect( )
downloadEpisodeLast$ = this.actions$.pipe(
ofType<episodeActions.DownloadEpisodes>( episodeActions.DOWNLOAD_EPISODE ),
switchMap( ( { payload } ) => this.episodesService.download( payload )
.pipe(
switchMap( (response: HttpEvent<any> | HttpResponse<any>) => this.episodesService.getHttpProgress( response ) ),
last(),
map( ( response: fromServices.DownloadProgress ) => {
console.log('Type 4', response);
if ( response.type === 4 ){
return new episodeActions.DownloadEpisodesSuccess( response, { ...payload, download: {
progress: response.progress
} } );
}
} ),
catchError( error => of( new episodeActions.DownloadEpisodesFail( error ) ) ),
)
)
)