2

I'm developing an angular app with multiple lazy loaded modules using angular cli. The resources (js, css and html) requires authorization which is set by a cookie. If the user is not signed in when loading the first page he will be redirected to a SSO log in page and then back to the app when successfully authorized. This flow is not something I can change.

The problem I have is that if the user loads one module, works in that module for a while and then leaves the page open but doesn't work with it more during the day. If the user then the next day starts with trying to load a route that requires another lazy module, that module will return a 401 since he no longer is authenticated. However, the user will not see that the module failed to load and feels like nothing happens.

I'm looking for a way to get notified when a lazy loaded module can't be loaded so I can redirect the user to the sign in page. Is this possible?

4
  • Is the redirection done with Guards? In that case I think you can trigger some event in case authentication fails and handle that in the AppComponent to display something. Commented Oct 25, 2017 at 7:16
  • No, the redirection is done server side when the when you load the index.html file. If I get 401 on a XHR request I do the redirection in code but don't know how to intercept 401 on static resources Commented Oct 25, 2017 at 8:05
  • Any progress on this? I'm stuck in the exact same scenario. Commented Jan 16, 2018 at 10:00
  • I "solved" this by having a custom error handler that catch all errors. If a lazy module fails to load it will throw an exception that the error handler can act upon and redirect the user to the sign in page. Commented Jan 16, 2018 at 11:02

1 Answer 1

2

By using a PreloadingStrategy that preloads the lazyloaded modules this can be prevented since the application no longer needs to GET the specific module on route change when the user is no longer authenticated.

preload-strategy.ts (taken from John Papa repo link)

import { PreloadingStrategy, Route } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';

export class PreloadSelectedModulesList implements PreloadingStrategy {
  preload(route: Route, load: Function): Observable<any> {
    return route.data && route.data['preload'] ? load() : of(null);
  }
}

app-routing.module.ts

import { PreloadSelectedModulesList } from './core/preload-strategy';
    const routes: Routes = [
        // Eagerly loaded
        { path: '', component: HomeComponent, pathMatch: 'full' },
        // Preloaded module
        { path: 'preloaded', loadChildren: './preloaded/preloaded.module#PreloadModule', data: {preload: true}},
        // Lazy loaded module
        { path: 'lazy', loadChildren: './lazy/lazy.module#LazyModule'}
    ];

@NgModule({
    imports: [
        RouterModule.forRoot(routes, {
            preloadingStrategy: PreloadSelectedModulesList
        })
    ],
    exports: [RouterModule],
    providers: [ PreloadSelectedModulesList, ..., ... ]
})

export class AppRoutingModule { }

There could still be a small edge-case where the user suddenly becomes unauthorized while trying to GET a module, in this case one workaround could be what Abris mentions above, extending Angulars ErrorHandler and checking thrown errors for module loading.

error-handler.ts

import { ErrorHandler } from '@angular/core';

export default class MyErrorHandler extends ErrorHandler {

 constructor() { 
   super();
 }

  handleError(error) {
      // Check and take appropriate actions
      ...
      // delegate to the default handler
      super.handleError(error); 

  }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.