Home > Back-end >  RXJS wait for response and then execute the next code
RXJS wait for response and then execute the next code

Time:11-03

So I am working with an Angular 14 project, where I have an backend api to fetch user data. My goal is to update the user data in public a variable in my service and check that variable's state to process next block of code. My code executes before rxjs observable updates the variable's state. If I log the data I can see the value is null, but when I expand it, I see that the state has changed with expected value.

code in service

getAuthenticatedUserProfile() {
    return this._http
      .get(`${environment.apiUrl}/user/state-profile`, {
        headers: GlobalHeaders.HTTP_HEADERS,
        observe: 'response',
        responseType: 'json',
        withCredentials: true
      })
      .subscribe({
        next: (data: any) => {
          let auth = data.body?.data;
          let payload = {
            userId: auth?.user_id,
            userName: auth?.user_name,
            userFullName: auth?.name,
            userEmail: auth?.email,
            roleName: auth?.role,
            profileId: auth?.profile_id,
            profileName: auth?.profile_name,
            userZone: auth?.zones,
            userState: auth?.states,
            userDistrict: auth?.districts,
            userAccessMenu: auth?.user_menus,
            allMenu: auth?.all_menus,
            isOtpRequired: auth?.require_otp,
            isLoggedIn: true
          };
          this.auth = payload;

          let localStoragePayload = {
            isOtpRequired: auth?.require_otp,
            isLoggedIn: true
          };
          localStorage.setItem('app_state', JSON.stringify(localStoragePayload)); 
            //temporary solution and I do not wish to use 
            //this if I can get a solution to wait 
            //for response to come
          this._store.dispatch(new UpdateAuthAction(payload));
        }
      });
  }

code in my component

constructor(private renderer: Renderer2, private _authService: AuthService, private router: Router) {}

  ngOnInit(): void {
    let configItems = JSON.parse(localStorage.getItem('appConfig') || '{}');
    this.appName = configItems.appName || 'Demo App';
    this.otpForm = new UntypedFormGroup({
      otp: new UntypedFormControl(null,[ Validators.required, Validators.pattern(/^\d{1,6}$/)])
    });
    this._authService.getAuthenticatedUserProfile();
    console.log(this._authService); 
    let storageItems = JSON.parse(localStorage.getItem('app_state') || JSON.stringify({}));
    if (!storageItems.isLoggedIn || !storageItems.isOtpRequired) {
      this.router.navigate(['/dashboard']);
    }
  }

area where the issue is present console.log(this._authService);

enter image description here

In the first line the the value is null, but when I expand it I can see the value has been mapped. Event with a settimeout of 500ms method I can read the value. I need to wait for data to update and then execute following code inside component without using of localstorge.

this.router.navigate(['/dashboard']);

Any guide is appriciated.

I would like to wait for rxjs update the value is service variable and then execute the next code block.

CodePudding user response:

Currently, you are returning a Subscription from getAuthenticatedUserProfile. What you want to do instead is to return an Observable which can then be subscribed in your component.

You can do side effects inside a tap. Afterwards, return the Observable.

import { tap } from "rxjs"

getAuthenticatedUserProfile() {
    return this._http
      .get(`${environment.apiUrl}/user/state-profile`, {
        headers: GlobalHeaders.HTTP_HEADERS,
        observe: 'response',
        responseType: 'json',
        withCredentials: true
      })
      .pipe(
        tap(data => {
           let auth = data.body?.data;
           
           //
           // ... rest of the body
           // 
        })
      )
}

And here is how you could use this in your component:

ngOnInit(): void {
  let configItems = JSON.parse(localStorage.getItem('appConfig') || '{}');
  this.appName = configItems.appName || 'Demo App';
  this.otpForm = new UntypedFormGroup({
    otp: new UntypedFormControl(null,[ Validators.required, Validators.pattern(/^\d{1,6}$/)])
  });
  this._authService.getAuthenticatedUserProfile().subscribe(() => {

    // do the things in here which need to wait for the call to finish

    console.log(this._authService); 
    let storageItems = JSON.parse(localStorage.getItem('app_state') || JSON.stringify({}));
    if (!storageItems.isLoggedIn || !storageItems.isOtpRequired) {
      this.router.navigate(['/dashboard']);
    }
  });
}
  • Related