I wonder if there's any chance to change the way the getUser function works. Right now it returns a promise with the User read from the configured storage. This is good for general cases, but in many others it turns out to be a pain when you have to hook it up with some other mechanisms that are not precisely very friendly with promises and async processes.
In my particular case, I am consuming the library from an Angular client and I have the event when the route changes (routeChangeStart), so I basically have to bring the user with UserManager.getUser() and in the promise success function validate that the user is authorized to navigate into that page. But the cycle and navigation already continued before being able to acquire the user, so I can't perform the authorization.
Perhaps having a sync version of the getUser function as well as the async promise-based one would be great. In the end, reading the storage in any browser natively has always been synchronous...
I am using angular 1.5.8. I instantiate the user manager and get the user back before I boot up angular. I then set the user manager as angular value on the app so I can resolve it with dependency injection. I have a angular service that resolves the user manager value. In the constructor I use getUser to resolve the user and set it as a scoped variable. The interface to the service allows me to check if the user has expired, get its access token, check its roles, etc... You could do the same and resolve the angular service and call the service in your routeChangeStart handler and check what you need. If you are using silent renewal you will need to update the user on your service when it renews.
Yeah, I have built a provider that is configured during app boot up, pretty much like the Cordova sample around there, but that's not my problem as all that part is working fine. The issue is when I, in any event that expects to resolve things synchronously, have to make a call to a promise, because the execution of such function will occur before the promise is resolved.
Check this snippet:
$rootScope.$on('$routeChangeStart', function (event, next, current) {
if (next.access) {
authorization.authorize(next.access.allowAnonymous, next.access.permissions, next.access.permissionCheckType)
.then(function (result) {
if (result === enums.authorised.notAuthorised) {
next.$$route.templateUrl = "notauthorized.html";
next.$$route.controller = null;
} else if (result === enums.authorised.loginRequired) {
$location.path('/').replace();
}
});
}
});
authorization.authorize() returns a promise because inside it, I have to make a call to UserManager.getUser, which also returns a promise. But routeChangeStart function ends and allows to continue navigation before I can correct the navigation flow in the promise callback.
This is the part causing me issues in such scenario and that's why I think it would be better to have a synchronous version of the store methods (because the native functions called inside the library also are sync instead of async).
The storage of the user is designed to allow for things like indexedDb, thus is must be async.
I get it, and that's why I suggested to have another version of the methods. Pretty much like in .Net when devs offer a method like "Submit" and "SubmitAsync". Here there could be getUserSync(), perhaps... So you can keep the async getUser() unmodified for all existing implementations.
I can hardly think of another way to circumvent an scenario like I'm having right now and I don't think it's a very weird or rare one...
that's why I suggested to have another version of the methods
Sounds like a leaky abstraction. Almost everything else is async in this library as well... just feels off...
I agree with @brockallen, everything in the library is designed to be async. Adding a method that is synchronous would be quite odd and even harmful, as it will lead people to use the synchronous method where they actually should be using the asynchronous one.
Don't get me wrong, I'm all for asynchronous methods whenever I can use them, even in .NET when doing APIs or any other stuff... But in this particular kind of scenarios, it's a lot of extra work to find or implement a workaround for something that should be pretty straighforward if there would be something synchronous like the native browser storage api.
Most helpful comment
Don't get me wrong, I'm all for asynchronous methods whenever I can use them, even in .NET when doing APIs or any other stuff... But in this particular kind of scenarios, it's a lot of extra work to find or implement a workaround for something that should be pretty straighforward if there would be something synchronous like the native browser storage api.