I have an use case in which I need to verify a few conditions. If the previous one fails I should not verify next one but based on the previous one I should display dialog with title and description indicates what went wrong.
Assuming I have an service (pseudo code)
// verify-condition.service.ts
public validateConditions():Observable<ValidationData> {
public validateConditions(): Observable<ValidationModal> {
const hasContract$: Observable<ContractStatus> = this.getContractSignStatus();
const hasTUTSigned$: Observable<boolean> = this.hasTUTSigned();
const doData$: Observable<DoModel> = this.getDoData();
return combineLatest([hasContract$, hasTUTSigned$, doData$]).pipe(
map(([hasContract, hasTUTSigned, doData,]) => {
const validationConditions: ValidationModal = {
conditions: {
hasContract: hasContract === ContractStatus.SIGNED,
hasTUTSigned,
wasSigned: doData.wasSigned,
valid: doData.valid,
signDate: doData.signDate,
}
};
return validationConditions;
})
);
}
}
and then in the component I’m using it
public verifyProcess(): void {
verifyConditionService.validateConditions().pipe(take(1)).subscribe((validationData:ValidationData=> {
if (validationData) {
this.modalValidationService.openModal(validationData);
} else {
this.beginProcess();
}
})
}
Thing is that in the service I run all the conditions at once using combineLatest but I would like to run them one by one and if the first fails I should not run the next one but instead throw an error or in some other way indicate that it fails and return data needed to display dialog.
public validateConditionsInOrder():Observable<ValidationData|boolean> {
return this.getContractSignStatus().pipe(
map((signStatus:ContractStatus)=>{
if(signStatus !== ContractStatus.SIGNED){
return {
hasContract:signStatus
}
} else {
return true;
}
}),
switchMap((previousCondition)=>{
if(!previousCondition){ // so if previous condition failed I DO NOT want to check the next conditions but instead stop verification and return the data from the previous condition
} else {
this.hasTUTSigned(); // if the previous condition is OK, I move on to the next one and so on. and if here or the next condition fails I always need to know what went wrong in orther to display dialog based on the info
}
})
)
}
2
Answers
You can probably create a chain of observables/calls using
iif
operator. Not the nicest solution, but you can use it as an inspiration and implement a custom pipe, as @Will Alexander has mentioned.Using
iif
andof
you can either chain real observables or pass unmodified validateConditions object if condition weren’t met.Here’s an example:
And a live demo on Stackblitz where you can toggle the conditions to return false when you want to see the different outputs.
The conditions are ran one after another, sequentially. If one fails (throws), it’ll kill the queue and you’ll get the error that you defined. So you could downstream easily rely on the error message to display something in your modal.
Have a play and see that at the moment with all conditions set to true, after 3s, you get the message "All conditions passed" but if you set one to
false
you’ll get an error and it’ll stop.