Ionic Firebase Angular异步验证报错:无法找到afDatabase
问题原因分析与修复方案
你遇到的核心问题是静态方法无法访问类的实例成员,再加上Angular依赖注入的使用方式错误,具体来说:
checkUsername是一个静态方法,静态方法属于类本身,而非类的实例,所以你在方法里用this.afDatabase时,this并不指向UsernameValidator的实例——而afDatabase是通过构造函数注入的实例属性,静态方法根本无法访问它。- 你在组件里直接调用
UsernameValidator.checkUsername,但从未创建过UsernameValidator的实例,构造函数里的AngularFireDatabase依赖根本没被初始化,自然会提示"无法找到afDatabase"。
另外还有一个小问题:原代码里的数据库查询写法不符合AngularFire2的规范,this.afDatabase.orderByChild('username').equals(control.value)是错误的调用方式,需要调整。
修复方案一:使用实例化验证器(推荐,符合Angular依赖注入规范)
这种方式是Angular推荐的做法,通过依赖注入创建验证器实例,让实例方法访问注入的数据库服务:
1. 修改username.ts,调整验证器类
import { Injectable } from '@angular/core'; import { FormControl } from '@angular/forms'; import { AngularFireDatabase } from 'angularfire2/database'; @Injectable() // 添加Injectable装饰器,让Angular可以注入依赖 export class UsernameValidator { constructor(private afDatabase: AngularFireDatabase) { } // 去掉static修饰符,改成实例方法 checkUsername(control: FormControl): Promise<any> { return new Promise(resolve => { // 正确构建AngularFire2查询:查询profile节点下username匹配的记录 this.afDatabase.list('profile', ref => ref.orderByChild('username').equalTo(control.value)) .valueChanges() .subscribe(matchedUsers => { // 如果有匹配的用户,说明用户名已被占用 resolve(matchedUsers.length > 0 ? { "username taken": true } : null); }); }); } }
2. 在模块中注册验证器
打开你的根模块(比如app.module.ts),把UsernameValidator添加到providers数组:
import { UsernameValidator } from './validators/username'; @NgModule({ // ... 其他配置项 providers: [ // ... 其他服务 UsernameValidator ] }) export class AppModule { }
3. 在组件中注入并使用验证器实例
修改profile-setup.ts,注入UsernameValidator并使用它的实例方法:
import { UsernameValidator } from '../../validators/username'; export class ProfileSetupPage { profile = {} as Profile; profileForm: FormGroup; // 注入UsernameValidator实例 constructor(private afAuth: AngularFireAuth, private afDatabase: AngularFireDatabase, public navCtrl: NavController, public navParams: NavParams, public formBuilder: FormBuilder, public toastCtrl: ToastController, private usernameValidator: UsernameValidator) { // 添加这一行 this.profileForm = formBuilder.group({ username: [ '', Validators.compose([Validators.required]), // 使用实例的checkUsername方法,bind确保this指向验证器实例 this.usernameValidator.checkUsername.bind(this.usernameValidator) ] }); } // ... 其他代码不变 }
修复方案二:静态方法中手动获取依赖(不推荐,仅作备选)
如果你想保留静态方法,可以通过Angular的Injector手动获取数据库服务实例,但这种方式不符合依赖注入的最佳实践:
1. 修改username.ts
import { FormControl } from '@angular/forms'; import { AngularFireDatabase } from 'angularfire2/database'; import { Injector } from '@angular/core'; export class UsernameValidator { private static afDatabase: AngularFireDatabase; // 静态方法初始化依赖 static initialize(injector: Injector) { UsernameValidator.afDatabase = injector.get(AngularFireDatabase); } static checkUsername(control: FormControl): Promise<any> { return new Promise(resolve => { UsernameValidator.afDatabase.list('profile', ref => ref.orderByChild('username').equalTo(control.value)) .valueChanges() .subscribe(matchedUsers => { resolve(matchedUsers.length > 0 ? { "username taken": true } : null); }); }); } }
2. 在根模块中初始化静态依赖
import { Injector } from '@angular/core'; import { UsernameValidator } from './validators/username'; export class AppModule { constructor(private injector: Injector) {} ngDoBootstrap() { UsernameValidator.initialize(this.injector); } }
内容的提问来源于stack exchange,提问作者jrocc
相关产品推荐
相关产品推荐

