Setup:
I have a function, isAuthorized(), in a singleton, AuthSessionSingleton which relies on the result of an async function.
The async function is an api call, called in the constructor, which expects the return of an object. isAuthorized() relies on that object.
Issue:
Some component calls the function isAuthorized() immediately, before the backend call resolves.
I want to be able to wait inside the isAuthorized() function until the backend call resolves and the object is no longer null.
Simple Code:
//auth.singleton.ts
@Injectable({providedIn: 'root'})
export class AuthSessionSingleton {
userInfo: UserInfo = null;
constructor(private service: MyService) {
this.loadUserInfo();
}
loadUserInfo() {
this.service.makeBackendCall().subscribe({
next: (obj: UserInfo) => {
this.userInfo = obj;
}
});
}
isAuthorized() {
if(this.userInfo == null) {
// do something to wait asynchronously
}
// Very simple example
if(this.userInfo.Role == 'Admin') {
return true;
}
return false;
}
}
//some.component.ts
export class SomeComponent {
authorized: boolean = false;
constructor(private auth: AuthSessionSingleton) {
this.checkAuthorization();
}
async checkAuthorization() {
this.authorized = await this.auth.isAuthorized();
}
}
In the above simplified program, SomeComponent calling isAuthorized() will likely check userInfo while it is still null. I need to wait for it to not be null.
Possible Solutions:
There are many solutions I've determined so far. I'm looking for the most correct solution and hopefully one that I haven't even thought of.
1. Listen to Subscription
In isAuthorized(), if(this.userInfo==null) subscribe to the same subscription made in loadUserInfo() and wait on it.
2. Wait Until Signaled
I could create a Subject in AuthSessionSingleton and Subscribe from SomeComponent, wait until I get a signal, then call IsAuthorized().
This seems especially roundabout.
3. Just Wait
There are many ways I could just spin my gears until the object I need is no longer null.
while(this.userInfo == null) {
// do something
}
Request:
I want a way to wait asynchronously in isAuthorized() until this.userInfo != null. Any number of calls can be made to isAuthorized() (from different components) and all of them should wait until that value is resolved.
Any ideas?
Edit
A more accurate use-case which I now realize changes the possible solutions follows. It is made more complex by accepting an array of values to loop through.
isAuthorized(roles: string[]) {
let(i = 0; i < roles.length; i++) {
let role = roles[i];
if(this.userInfo.Role == role) {
return true;
}
return false;
}
}
isAuthorized()function asynchronous and return the status after the call is complete. In solution 1, if you subscribe to the same end-point, you would be triggering an additional unwanted HTTP request. Solution 3 could potentially lead to an infinite loop if the back-end doesn't reply.