0
votes

I'm uploading a file to server and I would like to track upload progress without spamming with many actions (on each http event). Is it possible to return something like null or empty observable in some cases? Because I want to dispatch an action only in two cases - success or failure. And now I must return an action in each http event type and it's becoming a spam then..

@Effect()
public createMediaItem: Observable<Action> = this._actions
    .pipe(
        ofType(MediaItemActionTypes.MediaItemCreateAction),
        map((action: MediaItemCreateAction) => action),
        switchMap(action => {
            return this._uploadService.createMediaItem(action.formData)
                .pipe(
                    map((event: HttpEvent<HttpEventType>) => {
                        switch (event.type) {
                            case HttpEventType.UploadProgress: {
                                console.log('ignore');
                                action.fileItem.progress = Math.round(event.loaded / event.total * 100);
                                break;
                                // return;
                            }

                            case HttpEventType.Response: {
                                return new MediaItemCreateSuccessAction();
                            }
                            default:
                                break;
                            // return;
                        }
                    })
                );
        })
    );
3
You can't track an upload progress without HTTP events. for the first & last events, I would suggest handling it in the HTTP call directly, with tap and finalize, which would trigger at request creation and at request ending. - user4676340

3 Answers

0
votes

Use Rx.Observable.empty:

To return an empty action, you can use the empty observable from RxJS.

empty(scheduler: Scheduler): Observable

Creates an Observable that emits no items to the Observer and immediately emits a complete notification.

var result = Rx.Observable.empty();
result.subscribe(x => console.log(x));
0
votes

So, my solution is below. I decided not to dispatch an action straightly from effect, for that matter I use store to dispatch the action only when I need.

@Effect({ dispatch: false })
public createMediaItem: Observable<void> = this._actions
    .pipe(
        ofType(MediaItemActionTypes.MediaItemCreateAction),
        map((action: MediaItemCreateAction) => action),
        mergeMap(action => {
            return this._uploadService.createMediaItem(action.formData)
                .pipe(
                    map((event: HttpEvent<HttpEventType>) => {
                        switch (event.type) {
                            case HttpEventType.UploadProgress: {
                                action.fileItem.progress = Math.round(event.loaded / event.total * 100);
                                break;
                            }

                            case HttpEventType.Response: {
                                this._store.dispatch(new MediaItemCreateSuccessAction(action.fileItem, event.body));
                                break;
                            }

                            default:
                                break;
                        }
                    }),
                    catchError(error => of(this._store.dispatch(new MediaItemCreateFailAction(action.fileItem, error))))
                );
        })
    );
0
votes

The only solution that i found is returning an NeverObservable().

Rxjs 5.x.x Usage:

import {NeverObservable} from 'rxjs/observable/NeverObservable';
return NeverObservable.create();

The NeverObservable will just stop the effect directly without expecting a return of Observable