You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 17报错:Internal server error: localStorage is not defined求助

问题:Angular中UserStorageService报错"localStorage is not defined"

我正在配置UserStorageService实现应用登录登出功能,运行时出现错误:Internal server error: localStorage is not defined。以下是相关代码:

存储服务代码

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

const TOKEN = 'ecom-token'
const USER = 'ecom-user'

@Injectable({
  providedIn: 'root'
})
export class UserStorageService {

  constructor() { }

  public saveToken(token: string): void{
    window.localStorage.removeItem(TOKEN);
    window.localStorage.setItem(TOKEN,token);
  }

  public saveUser(user): void{
    window.localStorage.removeItem(USER);
    window.localStorage.setItem(USER, JSON.stringify(user));
  }

  static getToken(): string{
    return localStorage.getItem(TOKEN);
  }

  static getUser(): any{
    return JSON.parse(localStorage.getItem(USER));
  }

  static getUserId(): string{
    const user = this.getUser();
    if(user == null){
      return '';
    }
    return user.userId;
  }

  static getUserRole(): string{
    const user = this.getUser();
    if(user == null){
      return '';
    }
    return user.role;
  }

  static isAdminLoggedIn(): boolean{
    if(this.getToken === null){
      return false;
    }
    const role: string = this.getUserRole();
    return role == 'ADMIN';
  }

  static isCustomerLoggedIn(): boolean{
    if(this.getToken === null){
      return false;
    }
    const role: string = this.getUserRole();
    return role == 'CUSTOMER';
  }

  static signOut(): void{
    window.localStorage.removeItem(TOKEN);
    window.localStorage.removeItem(USER);
  }

}

应用组件代码

import { Component } from '@angular/core';
import { UserStorageService } from './services/storage/user-storage.service';
import { Router } from '@angular/router';


@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrl: './app.component.scss'
})
export class AppComponent {
  title = 'e-commerce';

  isCotumerLoggedIn : boolean = UserStorageService.isCustomerLoggedIn();
  isAdminLoggedIn : boolean = UserStorageService.isAdminLoggedIn();

  constructor(private router: Router){}

  ngOnInit(): void {
    this.router.events.subscribe(event => {
      this.isCotumerLoggedIn = UserStorageService.isCustomerLoggedIn();
      this.isAdminLoggedIn = UserStorageService.isAdminLoggedIn();
    })
  }


  logout(){
    UserStorageService.signOut();
    this.router.navigateByUrl('login')
  }


}

我已经检查过导入、重写代码,但问题仍未解决,请求帮助。


解决方案

核心问题分析

报错的根源有三点:

  1. 环境不兼容:如果应用启用了SSR(Angular Universal),服务端执行代码时没有浏览器的localStorage对象,直接访问会抛出未定义错误。
  2. 静态方法访问不一致:部分静态方法直接使用localStorage而非window.localStorage,在特殊环境下可能无法正确获取浏览器对象。
  3. 语法逻辑错误:isAdminLoggedIn和isCustomerLoggedIn中,this.getToken === null是引用方法而非调用方法,导致判断逻辑失效。

修复步骤

1. 统一存储访问逻辑并添加环境判断

修改UserStorageService,添加浏览器环境校验,统一通过window.localStorage访问,同时修复方法调用错误:

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

const TOKEN = 'ecom-token'
const USER = 'ecom-user'

@Injectable({
  providedIn: 'root'
})
export class UserStorageService {

  constructor() { }

  // 辅助方法:判断是否处于浏览器环境
  private static isBrowser(): boolean {
    return typeof window !== 'undefined' && typeof window.localStorage !== 'undefined';
  }

  public saveToken(token: string): void{
    if(!UserStorageService.isBrowser()) return;
    window.localStorage.removeItem(TOKEN);
    window.localStorage.setItem(TOKEN,token);
  }

  public saveUser(user): void{
    if(!UserStorageService.isBrowser()) return;
    window.localStorage.removeItem(USER);
    window.localStorage.setItem(USER, JSON.stringify(user));
  }

  static getToken(): string{
    if(!this.isBrowser()) return '';
    return window.localStorage.getItem(TOKEN) || '';
  }

  static getUser(): any{
    if(!this.isBrowser()) return null;
    const userStr = window.localStorage.getItem(USER);
    return userStr ? JSON.parse(userStr) : null;
  }

  static getUserId(): string{
    const user = this.getUser();
    if(user == null){
      return '';
    }
    return user.userId;
  }

  static getUserRole(): string{
    const user = this.getUser();
    if(user == null){
      return '';
    }
    return user.role;
  }

  static isAdminLoggedIn(): boolean{
    // 修复:调用getToken方法而非直接引用
    if(this.getToken() === ''){
      return false;
    }
    const role: string = this.getUserRole();
    return role === 'ADMIN';
  }

  static isCustomerLoggedIn(): boolean{
    // 修复:调用getToken方法而非直接引用
    if(this.getToken() === ''){
      return false;
    }
    const role: string = this.getUserRole();
    return role === 'CUSTOMER';
  }

  static signOut(): void{
    if(!this.isBrowser()) return;
    window.localStorage.removeItem(TOKEN);
    window.localStorage.removeItem(USER);
  }

}

2. 组件中延迟初始化登录状态

将组件中直接初始化登录状态的代码移到ngOnInit中,确保代码在浏览器环境执行:

import { Component } from '@angular/core';
import { UserStorageService } from './services/storage/user-storage.service';
import { Router } from '@angular/router';


@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrl: './app.component.scss'
})
export class AppComponent {
  title = 'e-commerce';

  isCotumerLoggedIn : boolean = false;
  isAdminLoggedIn : boolean = false;

  constructor(private router: Router){}

  ngOnInit(): void {
    // 初始化登录状态
    this.updateLoginStatus();
    this.router.events.subscribe(event => {
      this.updateLoginStatus();
    })
  }

  private updateLoginStatus(): void {
    this.isCotumerLoggedIn = UserStorageService.isCustomerLoggedIn();
    this.isAdminLoggedIn = UserStorageService.isAdminLoggedIn();
  }

  logout(){
    UserStorageService.signOut();
    this.router.navigateByUrl('login')
  }
}

额外注意事项

  • 如果未使用SSR仍报错,可能是代码在组件构造函数或模块初始化阶段就访问了localStorage,这些阶段可能还未挂载到浏览器环境,建议将相关逻辑移到ngOnInit或后续生命周期钩子中。
  • 始终通过window.localStorage访问存储,避免直接使用localStorage,确保跨环境的一致性。

内容的提问来源于stack exchange,提问作者CesarH1408

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 05:35:05