Search code examples
angulartypescriptionic-frameworkrxjsobserver-pattern

correct way of creating Stateless service Angular RxJs Observable


I need to maintain a stateless service using RxJs and Observables. So I have done this:

Note: Here I need to generate a work order number in a Reactive way and I store it on LocalStorage to avoid loos that Id on browser refresh/ App Killed use cases.

My doubt here is am I doing the correct way of creating Stateless service? If not what is the best way for that?

Note: All are working perfectly fine. But I need to know whether am I correct on this architecture or not?

work-orders-data.Service.ts

@Injectable({
    providedIn: 'root'
})
export class WorkOrdersDataService {

    private workOrderNumber: number = 1;
    private workOrderNumberSubject$: BehaviorSubject<number> = new BehaviorSubject<number>(this.workOrderNumber);
    workOrderNumberChanged$: Observable<number> = this.workOrderNumberSubject$.asObservable();

    constructor(

        private storage: Storage,
    ) { }



    setDefaultWorkOrderNumber(workOrderNumber: number): void {
        this.workOrderNumber = workOrderNumber;
    }

    setWorkOrderNumber(): void {
        this.workOrderNumber += 1;
        this.workOrderNumberSubject$.next(this.workOrderNumber);

        this.storage.set(LocalStorageConstant.WORK_ORDER_NUMBER, this.workOrderNumber);
    }
}

app.component.ts

 async initializeApp(): Promise<void> {

     this.workOrdersDataService.setDefaultWorkOrderNumber(Number(await this.storage.get(LocalStorageConstant.WORK_ORDER_NUMBER)));
}

work-order.component.ts

    createWorkOrder(): void {   

          this.workOrdersDataService.setWorkOrderNumber(); // to generate new work order no.

 this.workOrdersDataService.workOrderNumberChanged$.subscribe((res: number) => {

        const workOrderNumber: string = environment.companyEnvironment.workOrderPrefix + res; // work order no. creation

      });

      }

Solution

  • Architecture is good and legit.

    If you want to stretch the reactive approach, then convert initializeApp to an Observable.

    No need to use a Promise here.

    After all, the power of Observables is their global API abstraction over multiple APIs. (Promise / Fetch / Regular data structures like arrays/ etc...)

    What I would do is:

     initializeApp(): Observable<any> {
        return from(Number(this.storage.get(LocalStorageConstant.WORK_ORDER_NUMBER))).pipe(take(1)); // take(1) for auto completion.
     }
    

    and then subscribe to it in ngOnInit in your app.component.ts where you can and should call this.workOrdersDataService.setDefaultWorkOrderNumber

    Notice that there is no void signature here, but any instead since it will lack the subscribe function argument.

    Also, it might not be directly regarding this question, but I would consider a publishBehavior together with a refCount (refCount for auto subscription count) in your data service for a more "modern" writing over direct declaration of Subjects. (Which also allows you to use its .connect method to decide when to activate the subject rather then allocating it ahead in your data service).