RxJS - How Subscriber is different from Observable and Subscription?

Viewed 1837

I have been trying to find an example of wrapping Observable into a Subscriber to monitor async call's status e.g. loading, completed or errored. Can you provide a short example?

1 Answers

Not sure if this is what you mean, but you can wrap an async http call like so

const httpStream = Observable.create(observer => {

    fetch('http://server.com')
      .then(response => response.json()) 
      .then(data => {
        observer.next(data); // if http call provides progress as well as completion
                             // these can all be pushed with observer.next()
        observer.complete();
      })
      .catch(err => observer.error(err));

  });

  httpStream.subscribe(data => console.log(data));

Of course if it was actually fetch you wanted to wrap you could instead just do

var result = Rx.Observable.fromPromise(fetch('http://myserver.com/'));

EDIT: If you are using the angular HttpClient then there is no need to wrap it as it is already an observable. To get progress updates as well as the final response something like the following should work

const req = new HttpRequest('POST', 'http://api.server.com', body, {
    reportProgress: true
});

this._http.request(req)
.filter((event) => event.type === HttpEventType.UploadProgress || event instanceof HttpResponse)
.map((event) => {
    if (event.type === HttpEventType.UploadProgress) {
        const percentDone = Math.round(100 * event.loaded / event.total);
        return { type: 'uploadProgress', percentDone };
    } else if (event instanceof HttpResponse) {
        return { type: 'httpResponse', status: event.status };
    } 
})
.subscribe((response) => {
    if (response.type === 'uploadProgress') {
        console.log(`upload still in progress - percent done = ${response.percentDone}%`);
    } else {
        console.log(`upload completed  - status = ${response.status}`);
    }
});

If in fact all you want to know is when all the request have completed, and don't need the progress updates from each then rather than pushing the requests into an array a better option might be to use a forkJoin - which is similar to a promise.all in that you only get an output from the observable once all of the sub observables have completed - https://www.learnrxjs.io/operators/combination/forkjoin.html

Related