I have a component somewhat like the pseudo-code snippet at the bottom.
I need to amend onDeployForTesting()
so that it calls myService.save()
before calling myService.deployForTesting()
. I have been looking into nested Observables and nested calls to httpClient
but I can never tell which Observable failed (if one does). I need to know this so that I can continue to set notifications.
How do I nest two (or more) httpClient
requests, and see which one in the chain failed (in an RxJS way)?
onSaveAndDeployForTesting() {
this.myService
.save(arg1)
.pipe(
concatMap( // also tried: switchMap, mergeMap
() => this.myService.deployForTesting(arg2),
),
)
.subscribe(
console.info,
console.error, // this gives a very generic error with no pointer to which Observable actually failed
console.info,
);
}
class MyClass {
// other code
onSave() {
this.myService.save(arg1)
.subscribe(
(data) => {
this.notificationService.set({
type: NotificationType.SUCCESS,
title: 'Success',
description: 'Lorem ipsum dolor sit amet',
});
},
(err) => {
if (err.errorCode === 409) {
this.notificationService.set({
type: NotificationType.WARNING,
title: 'Save Conflict',
description: 'Lorem ipsum dolor sit amet',
});
} else {
this.notificationService.set({
type: NotificationType.ERROR,
title: 'Error',
description: 'Lorem ipsum dolor sit amet',
});
}
},
);
}
onDeployForTesting(arg1) {
this.myService.deployForTesting(arg1)
.subscribe(
(data) => {
if (data.status === 207) {
this.notificationService.set({
type: NotificationType.WARNING,
title: 'Unable to deploy configuration',
description: 'Lorem ipsum dolor sit amet',
});
} else {
this.notificationService.set({
type: NotificationType.SUCCESS,
title: 'Success',
description: 'Lorem ipsum dolor sit amet',
});
}
},
(err) => {
this.notificationService.set({
type: NotificationType.ERROR,
title: 'Error',
description: 'Lorem ipsum dolor sit amet',
});
},
);
}
}
class MyService {
// other code
save(data) {
return this.http.put('/my/save/url', data);
}
deployForTesting(data) {
return this.http.post('/my/deploy/url', data);
}
}
You could use RxJS catchError
. Try the following
import { throwError, of, EMPTY } from 'rxjs';
import { catchError, concatMap } from 'rxjs/operators';
onSaveAndDeployForTesting() {
this.myService.save(arg1).pipe(
catchError(saveError => this.handleSaveError(saveError)),
concatMap(() => this.myService.deployForTesting(arg2).pipe(
catchError(deployError => this.handleDeployError(deployError))
))
)
.subscribe(
console.info,
console.error,
console.info,
);
}
handleSaveError(error) {
// handle error from `save()` call
return EMPTY; // also `throwError()` or `of()`
}
handleDeployError(error) {
// handle error from `deployForTesting()` call
return EMPTY; // also `throwError()` or `of()`
}
Remember to return an observable from the catchError
.