Ошибка: Uncaught (в обещании): ReferenceError: localStorage не определен
Я программирую одностраничное приложение, используя Angular/Typescript. Приложение запускается со страницы входа. Когда пользователь аутентифицирован, новая страница загружается с использованием этой строки кода:
this.router.navigate(['/productionFiles']);
И это прекрасно работает! Также два пути маршрутизатора украшены canactivate [ AuthGuard ]
это canactivate
хорошо работает, когда приложения направляют пользователя на страницу производственных файлов. Но обновление на той же странице дает следующую ошибку:
Exception: Call to Node module failed with error: Error: Uncaught (in promise): Error: No provider for AuthGuard!
Кроме того, когда я ввожу вручную URL-адрес та же ошибка возникает?
Я знаю, что эта ошибка имеет много вопросов здесь. Но это немного отличается, я думаю. Так что, похоже, все работает хорошо, кроме случаев, когда есть обновление браузера или введенный вручную URL.
В сервисе аутентификации устанавливается локальное хранилище ('currentuser'):
localStorage.setItem('currentUser', JSON.stringify(user));
Поскольку я использую шаблон SPA для visual studio, есть 3 файла app.module:
App.Module.Shared.Ts:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { RouterModule, Routes } from '@angular/router';
import { AppComponent } from './components/app/app.component';
import { HomeComponent } from './components/home/home.component';
import { HeaderComponent } from './components/Header/header.component';
import { ProductionfileComponent } from './components/ProductionFile/productionfile.component';
import { ProductionFileSummary } from './components/ProductionFile/productionfilesummary.component';
import { ProductionFileDetailComponent } from './components/ProductionFile/productionfiledetail.component';
import { LoginComponent } from './components/Login/login.component';
import { AuthGuard } from './components/Login/auth.guard';
export const sharedConfig: NgModule = {
declarations: [
AppComponent,
HomeComponent,
HeaderComponent,
ProductionfileComponent,
ProductionFileSummary,
ProductionFileDetailComponent,
LoginComponent
],
imports: [
RouterModule.forRoot([
{ path: '', redirectTo: 'login', pathMatch: 'full' },
{ path: 'login', component: LoginComponent },
{ path: 'productionFiles', component: ProductionfileComponent, canActivate: [ AuthGuard ] },
{ path: 'productionfiledetail/:prodHeaderOrdNr', component: ProductionFileDetailComponent, canActivate: [ AuthGuard ] },
{ path: '**', redirectTo: 'login' }
]),
BrowserModule,
FormsModule
],
providers: [AuthGuard],
bootstrap: [AppComponent]
};
App.Module.Client.ts:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { sharedConfig } from './app.module.shared';
@NgModule({
declarations: sharedConfig.declarations,
imports: [
BrowserModule,
FormsModule,
HttpModule,
...sharedConfig.imports
],
providers: [ sharedConfig.providers,
{ provide: 'ORIGIN_URL', useValue: location.origin }
],
bootstrap: [sharedConfig.bootstrap]
})
export class AppModule {
}
App.Module.Server.ts:
import { NgModule } from '@angular/core';
import { ServerModule } from '@angular/platform-server';
import { sharedConfig } from './app.module.shared';
@NgModule({
declarations: sharedConfig.declarations,
imports: [
ServerModule,
...sharedConfig.imports
],
providers: sharedConfig.providers,
bootstrap: sharedConfig.bootstrap
})
export class AppModule {
}
Может кто-нибудь, пожалуйста, поставить меня на правильный путь?
2 ответа
Я думаю, что правильным способом является использование isPlatformBrowser, чтобы определить, выполняете ли вы код клиентской или серверной части
import { isPlatformBrowser } from '@angular/common';
import { PLATFORM_ID } from '@angular/core';
constructor(private router: Router,
private actvRoute: ActivatedRoute, @Inject(PLATFORM_ID) platformId: Object) { }
canActivate() {
console.log('AuthGuard.CanActivate')
//return true;
if(isPlatformBrowser(this.platformId))//<== means you are client side
{
if (localStorage.getItem('currentUser')) {
// logged in so return true
return true;
}
// not logged in so redirect to login page
this.router.navigate(['/login']);
return false;
}
else
{
//server side
}
}
Я обнаружил, что localstorage недоступен / не определен после обновления браузера. Поэтому я изменил код Auth.Guard.Ts. Не, если это правильно, но это работает, знай, как я этого ожидаю.
import { Injectable } from '@angular/core';
import { Router, ActivatedRoute, CanActivate } from '@angular/router';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private router: Router,
private actvRoute: ActivatedRoute) { }
canActivate() {
console.log('AuthGuard.CanActivate')
//return true;
try {
if (localStorage.getItem('currentUser')) {
// logged in so return true
return true;
}
// not logged in so redirect to login page
this.router.navigate(['/login']);
return false;
} catch (e) {
}
}
}