I have a service which interacts with an api server. It has myHttpPost(data) method. This method should:
The current version of my method is:
postData(path: string, data: Object): Rx.Observable<any> {
let json = JSON.stringify(data);
return this.http.post(path, json)
.map(res => res.json())
}
This is not doing point 3 from the above list, because map is only called upon success and not on error. I could change the sequence by adding:
.catch(error => {
let myError = prepareErrorContent(error);
return Rx.Observable.throw(myError);
});
Then the subscriber (another service) receives myError (that's ok) but the rxjs documentation says the following about catch() method: "Continues an observable sequence that is terminated by an exception with the next observable sequence." But I want the sequence to terminate normally and not to continue. If I use the catch()
like above, then the next call to postData() from the subscriber does not work (it immediately returns the same error instead of making the http call). I think it's because the sequence is not terminated.
How to do it?
[Edit] This is my subscriber method which uses this service:
this.jsonHttp.postData(path, data)
.subscribe(
struct => onNext(struct),
error => {
let message = this.jsonHttp.extractError(error);
onError(message)
},
() => onComplete ? onComplete() : null
);
Bookmark this question. Show activity on this post. When I create an observable from scratch, and have the observer error, then complete, the done part of the subscription never is invoked.
You'll need to use retry or retryWhen (names are pretty self-explanatory) — these operators will retry a failed subscription (resubscribe to the source observable, once an error is emitted.
The catchError operator takes as input an Observable that might error out, and starts emitting the values of the input Observable in its output Observable.
Another option to catch errors is to use the CatchError Operator. The CatchError Operators catches the error in the observable stream as and when the error happens. This allows us to retry the failed observable or use a replacement observable.
In fact, for each HTTP request a processing chain is created and executed. When the response is received (both successful and with error), the chain is completed.
If you execute twice the request, there is no link between them. You can have some links when both requests are part of the same processing chain. For example when using observable operators like flatMap
or switchMap
. Here is a sample:
return this.http.get(...)
.map(res => res.json())
.flatMap(jsonData => {
// Can leverage the result of the previous request
return this.http.get(...).map(res => res.json());
});
When an error occurs, the processing chain is broken and the catch
operator is called. You can return an observable in the associated callback to continue the processing chain. It can be a classical observable or an error one with Observable.throw
. In the context of an HTTP request in Angular2, a response with a status code different than 2xx is considered as an error.
When returning Observable.throw
, the second callback specified when subscribed is called. If it's another observable, the first callback is called. For example:
return this.http.get(...)
.map(res => res.json())
.catch(res => {
// The error callback (second parameter) is called
return Observable.throw(res.json());
// The success callback (first parameter) is called
// return Observable.of(res.json());
});
I implemented a plunkr that execute a request (clicking on a button) without authentication header, so a 401 status code is received. When you click again, the header is added, so a 200 status code is received. Just to show you that there is no relation between the two requests.
See this plunkr: https://plnkr.co/edit/5WwWpwjvQmJ4AlncKVio?p=preview.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With