In client side applications, we are calling service APIs to fetch or manipulate data, which is then used to represent or store user inputs. This cycle is the basic applications function, when the application grows, managing the various states associated with these requests can become complex at a stage. As the number of states and interactions rises, it becomes more challenging to maintain clarity and ensure consistency across different parts of the application components, potentially leading to issues with performance, state synchronization, and debugging.
In most cases, we need to handle data requests and ensured that the data is correctly persisted. This raise several important questions about how to mange and verify the data integrity throughout the process.
Would creating a wrapper for API requests be beneficial?
Yes, this would simplify request observability and create a more maintainable solution in a single place. Additionally, this allows us to manage activities such as tracking whether the processing state has ended or is still ongoing, making it easier to maintain and implement a waiter or loader as needed.
export class RequestContainer {
private static unsubscribe$ = new Subject<void>();
static processUpdate<T>(request: Observable<T>, callback: Function, state: RequestUpdateState, service: SaveStatePreserverService = null) {
state.requestCount++;
service?.publishState(state);
request.pipe(takeUntil(RequestContainer.unsubscribe$)).subscribe({
next: (response: T) => {
callback(response);
RequestContainer.decrementCount(state, service);
},
error: (err) => {
RequestContainer.decrementCount(state, service);
throw err;
}
});
}
static decrementCount(state: RequestUpdateState, service: SaveStatePreserverService = null) {
state.requestCount--;
if (state.requestCount < 0) {
state.requestCount = 0;
}
service?.publishState(state);
}
static cleanup() {
RequestContainer.unsubscribe$.next();
RequestContainer.unsubscribe$.complete();
}
}
export interface RequestUpdateState {
requestCount: number;
}
Additionally, to ensure that the update state is maintained in the service, allowing the information to be reflected in another place or component
@Injectable()
export class SaveStatePreserverService {
private state$ = new Subject<RequestUpdateState>();
publishState(value: RequestUpdateState) {
this.state$.next({ ...value });
}
getState(): Observable<RequestUpdateState> {
return this.state$.asObservable();
}
}
Here few examples,
sampleUpdateState: RequestUpdateState = {
requestCount: 0
};
//Example 1
saveContent() {
RequestContainer.processUpdate(this.service.updateContent(), () => {}, sampleUpdateState);
}
//Example 2
constructor(private saveStatePreserverService: SaveStatePreserverService) {}
saveContent() {
RequestContainer.processUpdate(this.service.updateContent(), this.callbackFunction.bind(this), sampleUpdateState, this.saveStatePreserverService);
}
callbackFunction(data) {
//Logic
}
This is the initial pattern, which we can adjust based on our requirements and extend as needed. It’s cleaner and more maintainable. Looking forward to more insights—stay tuned!

Comments