Reputation: 295
I have a component that upon button click calls a save()
method from a StorageManagerService
:
// component.ts
onSaveClick(): void {
this.storageManager
.save(<objectToSave>)
.pipe(take(1))
.subscribe({
next: (success: boolean) => {
if (success) {
// do stuff
} else {
// do other stuff
}
},
});
}
That storageManager is an adapter to another service that handles conditional logic. So StorageManagerService.save()
looks like the following:
// StorageManagerService
save(<objectToSave>): Observable<boolean> {
if (<someCondition>) {
this.modalService
.openDialogWithComponent(
SaveSystemContainerComponent,
{ data: { <someData> } },
this.matDialog
)
.afterClosed()
.pipe(take(1))
.subscribe({
next: (success: boolean) => {
if (success) {
// special handling
return this.localStorageService.save(<objectToSave>);
}
return of(false);
},
});
}
else {
return this.localStorageService.save(<objectToSave>);
}
}
While LocalStorageManagerService
has the concrete implementation for storing data:
// LocalStorageManagerService
save(<objectToSave>): Observable<boolean> {
if (this.storageAvailable()) {
localStorage.setItem(<objectToSave>.id, JSON.stringify(<objectToSave>));
return of(true);
}
console.error('local storage not available or disabled');
return of(false);
}
LocalStorageService
inherits from an abstract class that all storage services have to implement.
The idea is that when migrating from localStorage to an actual database in the future, I only have to change the variable in StorageManagerService
and don't have to modify 20+ places in the application.
The problem I'm having is that in certain conditions the user has to input additional data before I can store it. That input happens through a modal appearing.
Now TypeScript tells me that the if-case in StorageManagerService
doesn't return anything (which is correct).
How can I return the result from subscribe.next()
in StorageManagerService
to the calling function? I think I'm missing an rxjs operator.
Upvotes: 1
Views: 564
Reputation: 8295
If someone subscribes to save, you can refactor the method to:
save(objectToSave): Observable<boolean> {
if (someCondition) {
return this.modalService
.openDialogWithComponent(
SaveSystemContainerComponent,
{ data: { someData } },
this.matDialog
)
.afterClosed()
.pipe(
take(1),
switchMap((success: boolean) => {
if (success) {
// special handling
return this.localStorageService.save(objectToSave);
}
return of(false);
})
);
} else {
return this.localStorageService.save(objectToSave);
}
}
Also, your LocalStorageManagerService
should only do the actual save when a subscription is made to the return of save
, not only when save
is called:
save(objectToSave): Observable<boolean> {
return defer(() => {
if (this.storageAvailable()) {
localStorage.setItem(objectToSave.id, JSON.stringify(objectToSave));
return of(true);
}
console.error('local storage not available or disabled');
return of(false);
});
}
Upvotes: 3