Ionic 8(Angular 17)中No provider for Storage错误解决求助
Ionic 8(Angular 17)配置Ionic Storage时出现No provider for Storage错误
在Ionic 8(Angular 17)环境中配置Ionic Storage,浏览器控制台抛出错误:
ERROR NullInjectorError: NullInjectorError: No provider for Storage!
我已按照官方文档尝试在独立服务中实现Ionic Storage,相关代码如下:
storage.service.ts
import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root', }) export class StorageService { private _storage: Storage | null = null; constructor(private storage: Storage) { this.init(); } async init() { const storage = await this.storage['create'](); this._storage = storage; } public async get(key: string) { const value = await this._storage?.['get'](key); return value; } public async set(key: string, value: any) { await this._storage?.['set'](key, value); } }
auth.service.ts
import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { StorageService } from './storage.service'; interface Credentials { username: string; password: string; } export interface AuthResponse { auth_token: string; } @Injectable({ providedIn: 'root', }) export class AuthService { constructor( private httpClient: HttpClient, private storageService: StorageService ) {} async getAuthToken(): Promise<string> { const token = await this.storageService.get('token'); return token; } async isAuthenticated(): Promise<boolean> { const token = await this.getAuthToken(); if (token) { return true; } return false; } authenticate(credentials: Credentials): Observable<AuthResponse> { return this.httpClient.post<AuthResponse>( `${import.meta.env['NG_APP_API_BASE_URL']}/${ import.meta.env['NG_APP_API_PREFIX'] }/token/login`, credentials ); } async processPostLoginOps(token: string): Promise<void> { await this.storageService.set('token', token); const authenticated = await this.isAuthenticated(); if (authenticated) { throw new Error('Unable to login'); } } }
login.page.ts
import { CommonModule } from '@angular/common'; import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators, } from '@angular/forms'; import { Router } from '@angular/router'; import { IonButton, IonCard, IonCardContent, IonCol, IonContent, IonGrid, IonHeader, IonInput, IonItem, IonList, IonNav, IonRow, IonTitle, IonText, IonToolbar, } from '@ionic/angular/standalone'; import { LoadingController, ToastController } from '@ionic/angular'; import { AuthService, AuthResponse } from 'src/app/services/auth.service'; import { Capacitor } from '@capacitor/core'; @Component({ selector: 'app-login', templateUrl: './login.page.html', styleUrls: ['./login.page.scss'], standalone: true, imports: [ IonButton, IonCard, IonCardContent, IonCol, IonContent, IonGrid, IonHeader, IonInput, IonItem, IonList, IonNav, IonRow, IonTitle, IonText, IonToolbar, CommonModule, FormsModule, ReactiveFormsModule ], }) export class LoginPage implements OnInit { form!: FormGroup; disabled: boolean = true; loadingOverlay!: HTMLIonLoadingElement; errorToast!: HTMLIonToastElement; constructor( private router: Router, private formBuilder: FormBuilder, private loadingController: LoadingController, private toastController: ToastController, private authService: AuthService ) {} async ngOnInit(): Promise<void> { this.initForm(); this.subscribeToFormChanges(); await this.setOrResetLoadingOverlay(); await this.setToasts(); } private async setToasts() { this.errorToast = await this.toastController.create({ duration: 1500, position: 'bottom' }); } private async setOrResetLoadingOverlay() { this.loadingOverlay = await this.loadingController.create({}); } initForm(): void { this.form = this.formBuilder.group({ username: ['', Validators.required], password: ['', Validators.required], }); } subscribeToFormChanges(): void { this.form.statusChanges.subscribe((status) => { if (status === 'VALID') { this.disabled = false; } else { this.disabled = true; } }); } async authenticate() { this.loadingOverlay.message = 'Logging in'; await this.loadingOverlay.present(); this.authService .authenticate({ username: this.form.value.username, password: this.form.value.password, }) .subscribe({ next: async (response: AuthResponse) => { this.loadingOverlay.dismiss(); this.loadingOverlay.message = 'fdnfgnfgn'; this.loadingOverlay.present(); try { this.authService.processPostLoginOps(response.auth_token); this.router.navigate(['/']).then(() => window.location.reload()); } catch (error) { await this.setOrResetLoadingOverlay(); this.errorToast.message = 'Unable to login'; this.errorToast.present(); } }, error: async (error: any) => { this.loadingOverlay.dismiss(); await this.setOrResetLoadingOverlay(); this.errorToast.message = 'Unable to login'; this.errorToast.present(); }, }); } register(): void { this.router.navigate(['/register']); } }
解决方案
错误核心原因:未在Angular依赖注入系统中注册Storage提供者,导致StorageService无法获取到Storage实例。
1. 确认依赖安装
确保已安装必要包:
npm install @ionic/storage-angular @capacitor/storage
2. 修正StorageService实现
在独立组件架构下,无需依赖注入Storage,直接手动创建实例更简洁:
import { Injectable } from '@angular/core'; import { Storage } from '@ionic/storage-angular'; @Injectable({ providedIn: 'root', }) export class StorageService { private _storage: Storage | null = null; constructor() { this.init(); } async init() { // 手动初始化Storage实例 const storage = new Storage({ name: '__authdb', driverOrder: ['indexeddb', 'websql'] // 根据环境选择存储驱动 }); this._storage = await storage.create(); } public async get(key: string) { return this._storage?.get(key); } public async set(key: string, value: any) { return this._storage?.set(key, value); } }
3. 修复AuthService逻辑错误
processPostLoginOps方法中逻辑颠倒,应在未验证成功时抛出错误:
async processPostLoginOps(token: string): Promise<void> { await this.storageService.set('token', token); const authenticated = await this.isAuthenticated(); if (!authenticated) { // 修改为!authenticated throw new Error('Unable to login'); } }
4. 验证配置
重启应用后,登录成功可在浏览器开发者工具的Application -> IndexedDB中查看是否存储了token,同时控制台不再抛出No provider for Storage错误。
内容的提问来源于stack exchange,提问作者Tirthya Kamal Dasgupta
相关产品推荐
相关产品推荐

