Async function in run() with AngularJS - angularjs

I'm searching a solution but it's always the same and she's not correpond to my problem.
I have a lot of route element but for all routes with different controller I need to know if the user is authenticate or not. If yes, I have a token from an api and if no, I have a token too. So I need to have a token from an api when I load all controllers.
So I don't want to make a resolve for each "when()", I don't want to ddos the API so I search a system like this with
app.run(['Auth', function(Auth){
// Call my service & waiting his resolve
// When resolved, continue the init
}]);
So how can I make a resolve system with my "Auth" service on the run() ?

Make a service where you will have variable with status of authentication, inject this service in all controllers and in each controller call method of that service. Inside that method check variable with authentication status and only if authentication request was not yet send - send it (and set variable to status sent).

Related

In NestJS how to get request object in service without injecting request from controller

How can I inject the request or the execution context in a service without the help of controller without any performance issues?
The docs make it very clear that to pass the request to a service you can use a REQUEST scoped service with #Inject(REQUEST) or you can get the request in the controller via #Req() and pass that to the service method.
There is nestjs-cls which may be helpful as well, but generally, you either pass it on or you take the performance hit for REQUEST scoping the provider.

Blocking / Initialization service with angular.js

My apps are using many web services on the intranet, and url-s for those depend on the server environment.
My apps are hosted on IIS, which adds an HTTP response header like this: Environment: DEV, so every web app knows in which server environment it is running, and thus which intranet servers it must use to call all the services.
Each of my angular apps uses a service that issues a simple GET against the app's own root just to get any response with the environment name in it, and set configuration accordingly.
Question:
How should an angular app implement such a service that would execute as the very first thing in the application, and make sure that while it is getting that first response, nothing in the app tries to execute an HTTP request against other services, or even try to use any configuration provided by my environment service?
Is there a way to implement such a service in angular that could block every other service / factory in the application till it is done initializing itself?
I have many other services in the app, and none of them really know what to do till my environment service has finished its initialization.
UPDATE
Looking at it from another angle.... is it possible to implement such an interceptor in angular that could do the following?:
execute an HTTP request and block the app's execution till it gets a response
make information from the response available throughout the app as a service/factory/config.
Angular lifecycle could be one solution. Using the angular.config() phase you could peek at the headers of the HTTP service.
Create a factory called 'httpInterceptor'
function httpInterceptors(siteConfig, $q, $injector) {
return {
response: function(data, status, headers) {
siteConfig.setEnvironment(headers['Environment']);
return data;
}
};
)
Then in angular.config()
$httpProvider.interceptors.push('httpInterceptor');
If you truly want to block the other option is to use UI router resolve property to block routes loading until the request has been made https://github.com/angular-ui/ui-router/wiki you can add the resolve method to the root state.
Resolve
You can use resolve to provide your controller with content or data that > is custom to the state. resolve is an optional map of dependencies which > should be injected into the controller.
If any of these dependencies are promises, they will be resolved and converted to a value before the controller is instantiated and the $stateChangeSuccess event is fired.

How to use two separate $http service instances in AngularJS?

I am implementing an angularjs service, which saves the data sent by an $http call in localStorage. In order to do that, I am using the request interceptor, so that whenever an http request is sent via $http, the data is saved in localStorage. Below is my code for the interceptor,
var OfflinkJs = angular.module('OfflinkJs', []);
OfflinkJs.factory('cacheInterceptor', function () {
var cacheInterceptor = {
request: function (config) {
// Here I am saving the config as a string in localstorage
return config;
}
};
return cacheInterceptor;
});
For above interceptor to work, I have to register it in the interceptors array of $httpProvider. I have done this to achieve that,
OfflinkJs.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push('cacheInterceptor');
}]);
PROBLEM
Now, when I use OfflinkJS module in another module, all the $http calls go through my interceptor. But I would like to make some requests sent by $http service use my interceptor while some other requests NOT.
Since $http service is a singleton, I cannot figure out how to use two instances of it in separate places of my application. Is there any way to achieve this?
I went through this question, but seems it really addresses the issue of Circular dependency
I need two instances of AngularJS $http service or what?
I check the URL in the interceptor and use that to filter out requests to other services. I set the base url for my service as a constant in my module, and then check against that. If the request isn't to the relevant service, it just passes through with no action.
But perhaps a better way would be to set up a data service instead of an interceptor. There are plenty of tutorials out there on data services.

Angularjs Interceptor Circular Dependency when using Refresh Tokens

Long story short, I have a structure in my angularjs app which is basically the following:
1. There is an 'authService' that is in charge of requesting access tokens, and refresh tokens.
2. There is an 'authInterceptorService' that adds the token to the header of the request, however, the tricky part is here: this service depends on the authService, for generating a new access token using a refresh token in case the access token is expired and the request is 401en, which means there will ultimately be a circular dependency, when I use the $httpProvider service to register the interceptor:
authService <- authInterceptorService <- $http <- authService
My questions is how is it possible to get around this issue when your interceptor needs to be able to issue a new access token using the refresh token and REsend the request?
One way to get around this would be use to Angular's event system. Since you are dealing with services you would probably need to broadcast the event ($emit) and listen for it ($on) on $rootScope.
For example, you can setup a listener for a 'tokenExpired' event that calls your token refresh service, which when successful fires a 'tokenRefreshed' event. When a request is 401'd you emit the tokenExpired event and register a one-time listener for the tokenRefreshed event in order to re-send the request after the refresh.
Maybe not the cleanest solution, but I've used setups like this when dealing with gnarly dependency chains and it works pretty well.

Angular injection loop

I am having a problem in my AngularJS and I cannot seem to find easy solution out of it.
I am using two services for user authorization with the server. The authorisation is based on two tokens: Access token and Refresh token.
Now I have one service (Auth) that takes care of the whole authorisation process and second service (Api) that takes care of communication with the server.
The way the authorisation works is that user accesses data with his Access Token. Once the token is invalitated, it will try to submit refresh token and hopefully get back new access token.
The problem is that if server responds with 401 and the token is invalidated I want to simply run Auth.authenticate(); on the background (no redirects or anything) and if successful continue with tthe new access token.
Unfortunately since Auth service is using Api service , I cannot inject Auth service back to the Api service. Is there any good way to do what I want to do from one global place(So I dont have to call the re-authorization after every single request in controller)?
Some architectural info:
Auth Service (injects Api Service)
| ---- authorisation function (uses Api Service)
Api Service
| ---- Different functions to prepare data for request
| ---- One function to send all requests
| ---- One function to handle all rejected promisses which includes detection of 401 and should include "silent" re-authorisation (AuthService.authorisation)
I really hope it doesnt sound too confusing.
I have tried interceptors, but the outcome is the same - injector loop.
The only idea I have, without changing my architecture, is if there is any way to get current active instance of the Auth service, as it is loaded anyway. But couldn't find any details on that.
Thank you!
I had a similar problem, also with my authorisation.
Sometimes re-architecting is the best solution, but I think in this case you have a good use-case for wanting the 'circular' access you are describing.
Try the following:
Inject $injector into your API service instead of your Auth service.
User $injector.get('AuthService') to get the instantiated Auth service.

Resources