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);
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']);
}
});
}